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#include "src/v8.h" 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_ARM64 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-factory.h" 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-stubs.h" 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h" 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler.h" 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/debug.h" 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/full-codegen.h" 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/ic.h" 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/isolate-inl.h" 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/parser.h" 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/scopes.h" 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm64/code-stubs-arm64.h" 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm64/macro-assembler-arm64.h" 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen 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: 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm_; 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label patch_site_; 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg_; 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool info_emitted_; 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Generate code for a JS function. On entry to the function the receiver 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// and arguments have been pushed on the stack left to right. The actual 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// argument count matches the formal parameter count expected by the 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// function. 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The live registers are: 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// - x1: the JS function object being called (i.e. ourselves). 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// - cp: our context. 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// - fp: our caller's frame pointer. 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// - jssp: stack pointer. 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// - lr: return address. 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The function builds a JS frame. See JavaScriptFrameConstants in 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// frames-arm.h for its layout. 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::Generate() { 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CompilationInfo* info = info_; 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch handler_table_ = 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED); 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch profiling_counter_ = isolate()->factory()->NewCell( 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate())); 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetFunctionPosition(function()); 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Function compiled by full code generator"); 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ProfileEntryHookStub::MaybeCallEntryHook(masm_); 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (strlen(FLAG_stop_at) > 0 && 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Debug("stop-at", __LINE__, BREAK); 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Sloppy mode functions and builtins need to replace the receiver with the 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // global proxy when called as functions (without an explicit receiver 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // object). 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (info->strict_mode() == SLOPPY && !info->is_native()) { 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label ok; 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int receiver_offset = info->scope()->num_parameters() * kXRegSize; 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(x10, receiver_offset); 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotRoot(x10, Heap::kUndefinedValueRootIndex, &ok); 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x10, GlobalObjectMemOperand()); 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x10, FieldMemOperand(x10, GlobalObject::kGlobalProxyOffset)); 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Poke(x10, receiver_offset); 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&ok); 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Open a frame scope to indicate that there is a frame on the stack. 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The MANUAL indicates that the scope shouldn't actually generate code 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to set up the frame because we do it manually below. 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope frame_scope(masm_, StackFrame::MANUAL); 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This call emits the following sequence in a way that can be patched for 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // code ageing support: 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push(lr, fp, cp, x1); 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Add(fp, jssp, 2 * kPointerSize); 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info->set_prologue_offset(masm_->pc_offset()); 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Prologue(info->IsCodePreAgingActive()); 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info->AddNoFrameRange(0, masm_->pc_offset()); 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Reserve space on the stack for locals. 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { Comment cmnt(masm_, "[ Allocate locals"); 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int locals_count = info->scope()->num_stack_slots(); 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generators allocate locals, if any, in context slots. 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!info->function()->is_generator() || locals_count == 0); 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (locals_count > 0) { 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (locals_count >= 128) { 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label ok; 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(jssp.Is(__ StackPointer())); 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Sub(x10, jssp, locals_count * kPointerSize); 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(x10, Heap::kRealStackLimitRootIndex); 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(hs, &ok); 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&ok); 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x10, Heap::kUndefinedValueRootIndex); 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_optimize_for_size) { 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushMultipleTimes(x10 , locals_count); 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kMaxPushes = 32; 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (locals_count >= kMaxPushes) { 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int loop_iterations = locals_count / kMaxPushes; 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x3, loop_iterations); 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label loop_header; 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&loop_header); 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do pushes. 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushMultipleTimes(x10 , kMaxPushes); 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Subs(x3, x3, 1); 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(ne, &loop_header); 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int remaining = locals_count % kMaxPushes; 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit the remaining pushes. 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushMultipleTimes(x10 , remaining); 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool function_in_register_x1 = true; 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (heap_slots > 0) { 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Argument to NewContext is the function, which is still in x1. 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Allocate context"); 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool need_write_barrier = true; 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_harmony_scoping && info->scope()->is_global_scope()) { 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x10, Operand(info->scope()->GetScopeInfo())); 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x1, x10); 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kNewGlobalContext, 2); 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (heap_slots <= FastNewContextStub::kMaximumSlots) { 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FastNewContextStub stub(isolate(), heap_slots); 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallStub(&stub); 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Result of FastNewContextStub is always in new space. 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch need_write_barrier = false; 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x1); 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kNewFunctionContext, 1); 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch function_in_register_x1 = false; 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Context is returned in x0. It replaces the context passed to us. 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // It's saved in the stack and kept live in cp. 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(cp, x0); 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(x0, MemOperand(fp, StandardFrameConstants::kContextOffset)); 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Copy any necessary parameters into the context. 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int num_parameters = info->scope()->num_parameters(); 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < num_parameters; i++) { 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* var = scope()->parameter(i); 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->IsContextSlot()) { 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int parameter_offset = StandardFrameConstants::kCallerSPOffset + 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (num_parameters - 1 - i) * kPointerSize; 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load parameter from stack. 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x10, MemOperand(fp, parameter_offset)); 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store it in the context. 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand target = ContextMemOperand(cp, var->index()); 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(x10, target); 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update the write barrier. 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (need_write_barrier) { 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteContextSlot( 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cp, target.offset(), x10, x11, kLRHasBeenSaved, kDontSaveFPRegs); 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (FLAG_debug_code) { 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfInNewSpace(cp, &done); 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Abort(kExpectedNewSpaceObject); 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* arguments = scope()->arguments(); 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (arguments != NULL) { 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Function uses arguments object. 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Allocate arguments object"); 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!function_in_register_x1) { 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load this again, if it's used by the local context below. 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x3, x1); 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Receiver is just before the parameters on the caller's stack. 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int num_parameters = info->scope()->num_parameters(); 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = num_parameters * kPointerSize; 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Add(x2, fp, StandardFrameConstants::kCallerSPOffset + offset); 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x1, Smi::FromInt(num_parameters)); 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x3, x2, x1); 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Arguments to ArgumentsAccessStub: 262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // function, receiver address, parameter count. 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The stub will rewrite receiver and parameter count if the previous 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // stack frame was an arguments adapter frame. 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArgumentsAccessStub::Type type; 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (strict_mode() == STRICT) { 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch type = ArgumentsAccessStub::NEW_STRICT; 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (function()->has_duplicate_parameters()) { 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch type = ArgumentsAccessStub::NEW_SLOPPY_SLOW; 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch type = ArgumentsAccessStub::NEW_SLOPPY_FAST; 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArgumentsAccessStub stub(isolate(), type); 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallStub(&stub); 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetVar(arguments, x0, x1, x2); 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_trace) { 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kTraceEnter, 0); 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Visit the declarations and body unless there is an illegal 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // redeclaration. 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (scope()->HasIllegalRedeclaration()) { 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Declarations"); 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scope()->VisitIllegalRedeclaration(this); 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { Comment cmnt(masm_, "[ Declarations"); 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (scope()->is_function_scope() && scope()->function() != NULL) { 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableDeclaration* function = scope()->function(); 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(function->proxy()->var()->mode() == CONST || 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch function->proxy()->var()->mode() == CONST_LEGACY); 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(function->proxy()->var()->location() != Variable::UNALLOCATED); 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitVariableDeclaration(function); 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitDeclarations(scope()->declarations()); 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { Comment cmnt(masm_, "[ Stack check"); 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label ok; 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(jssp.Is(__ StackPointer())); 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(jssp, Heap::kStackLimitRootIndex); 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(hs, &ok); 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PredictableCodeSizeScope predictable(masm_, 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::kCallSizeWithRelocation); 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET); 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&ok); 314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { Comment cmnt(masm_, "[ Body"); 317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(loop_depth() == 0); 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitStatements(function()->body()); 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(loop_depth() == 0); 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Always emit a 'return undefined' in case control fell off the end of 323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the body. 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { Comment cmnt(masm_, "[ return <undefined>;"); 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitReturnSequence(); 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Force emission of the pools, so they don't get emitted in the middle 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of the back edge table. 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm()->CheckVeneerPool(true, false); 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm()->CheckConstPool(true, false); 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::ClearAccumulator() { 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x0, Smi::FromInt(0)); 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitProfilingCounterDecrement(int delta) { 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x2, Operand(profiling_counter_)); 343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x3, FieldMemOperand(x2, Cell::kValueOffset)); 344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Subs(x3, x3, Smi::FromInt(delta)); 345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(x3, FieldMemOperand(x2, Cell::kValueOffset)); 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitProfilingCounterReset() { 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int reset_value = FLAG_interrupt_budget; 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (info_->is_debug()) { 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Detect debug break requests as soon as possible. 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reset_value = FLAG_interrupt_budget >> 4; 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x2, Operand(profiling_counter_)); 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x3, Smi::FromInt(reset_value)); 357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(x3, FieldMemOperand(x2, Cell::kValueOffset)); 358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt, 362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* back_edge_target) { 363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(jssp.Is(__ StackPointer())); 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Back edge bookkeeping"); 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Block literal pools whilst emitting back edge code. 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::BlockPoolsScope block_const_pool(masm_); 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label ok; 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(back_edge_target->is_bound()); 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We want to do a round rather than a floor of distance/kCodeSizeMultiplier 371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to reduce the absolute error due to the integer division. To do that, 372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // we add kCodeSizeMultiplier/2 to the distance (equivalent to adding 0.5 to 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the result). 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int distance = 375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm_->SizeOfCodeGeneratedSince(back_edge_target) + 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); 390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(stmt->EntryId(), 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. 394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS); 395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitReturnSequence() { 399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Return sequence"); 400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (return_label_.is_bound()) { 402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&return_label_); 403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&return_label_); 406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_trace) { 407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the return value on the stack as the parameter. 408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Runtime::TraceExit returns its parameter in x0. 409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(result_register()); 410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kTraceExit, 1); 411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(x0.Is(result_register())); 412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pretend that the exit is a backwards jump to the entry. 414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int weight = 1; 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (info_->ShouldSelfOptimize()) { 416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch weight = FLAG_interrupt_budget / FLAG_self_opt_count; 417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int distance = masm_->pc_offset() + kCodeSizeMultiplier / 2; 419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch weight = Min(kMaxBackEdgeWeight, 420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Max(1, distance / kCodeSizeMultiplier)); 421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitProfilingCounterDecrement(weight); 423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label ok; 424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(pl, &ok); 425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); 426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Call(isolate()->builtins()->InterruptCheck(), 427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RelocInfo::CODE_TARGET); 428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(x0); 429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitProfilingCounterReset(); 430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&ok); 431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Make sure that the constant pool is not emitted inside of the return 433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // sequence. This sequence can get patched when the debugger is used. See 434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // debug-arm64.cc:BreakLocationIterator::SetDebugBreakAtReturn(). 435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstructionAccurateScope scope(masm_, 437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::kJSRetSequenceInstructions); 438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeGenerator::RecordPositions(masm_, function()->end_position() - 1); 439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordJSReturn(); 440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This code is generated using Assembler methods rather than Macro 441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Assembler methods because it will be patched later on, and so the size 442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of the generated code must be consistent. 443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& current_sp = __ StackPointer(); 444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Nothing ensures 16 bytes alignment here. 445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!current_sp.Is(csp)); 446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(current_sp, fp); 447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int no_frame_start = masm_->pc_offset(); 448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldp(fp, lr, MemOperand(current_sp, 2 * kXRegSize, PostIndex)); 449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Drop the arguments and receiver and return. 450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(all): This implementation is overkill as it supports 2**31+1 451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // arguments, consider how to improve it without creating a security 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // hole. 453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr_pcrel(ip0, (3 * kInstructionSize) >> kLoadLiteralScaleLog2); 454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(current_sp, current_sp, ip0); 455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(); 456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ dc64(kXRegSize * (info_->scope()->num_parameters() + 1)); 457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EffectContext::Plug(Variable* var) const { 464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const { 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->GetVar(result_register(), var); 471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::StackValueContext::Plug(Variable* var) const { 475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->GetVar(result_register(), var); 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(result_register()); 478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::TestContext::Plug(Variable* var) const { 482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // For simplicity we always test the accumulator register. 484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->GetVar(result_register(), var); 485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); 486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->DoTest(this); 487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Root values have no side effects. 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::AccumulatorValueContext::Plug( 496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::RootListIndex index) const { 497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(result_register(), index); 498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::StackValueContext::Plug( 502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::RootListIndex index) const { 503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(result_register(), index); 504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(result_register()); 505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const { 509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), true, true_label_, 510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch false_label_); 511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (index == Heap::kUndefinedValueRootIndex || 512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch index == Heap::kNullValueRootIndex || 513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch index == Heap::kFalseValueRootIndex) { 514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (false_label_ != fall_through_) __ B(false_label_); 515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (index == Heap::kTrueValueRootIndex) { 516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (true_label_ != fall_through_) __ B(true_label_); 517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(result_register(), index); 519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->DoTest(this); 520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const { 525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::AccumulatorValueContext::Plug( 529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> lit) const { 530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(result_register(), Operand(lit)); 531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { 535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Immediates cannot be pushed directly. 536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(result_register(), Operand(lit)); 537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(result_register()); 538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { 542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), 543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch true, 544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch true_label_, 545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch false_label_); 546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!lit->IsUndetectableObject()); // There are no undetectable literals. 547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { 548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (false_label_ != fall_through_) __ B(false_label_); 549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (lit->IsTrue() || lit->IsJSObject()) { 550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (true_label_ != fall_through_) __ B(true_label_); 551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (lit->IsString()) { 552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (String::cast(*lit)->length() == 0) { 553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (false_label_ != fall_through_) __ B(false_label_); 554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (true_label_ != fall_through_) __ B(true_label_); 556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (lit->IsSmi()) { 558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (Smi::cast(*lit)->value() == 0) { 559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (false_label_ != fall_through_) __ B(false_label_); 560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (true_label_ != fall_through_) __ B(true_label_); 562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // For simplicity we always test the accumulator register. 565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(result_register(), Operand(lit)); 566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->DoTest(this); 567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EffectContext::DropAndPlug(int count, 572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg) const { 573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(count > 0); 574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Drop(count); 575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::AccumulatorValueContext::DropAndPlug( 579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int count, 580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg) const { 581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(count > 0); 582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Drop(count); 583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(result_register(), reg); 584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::StackValueContext::DropAndPlug(int count, 588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg) const { 589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(count > 0); 590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (count > 1) __ Drop(count - 1); 591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Poke(reg, 0); 592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::TestContext::DropAndPlug(int count, 596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg) const { 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(count > 0); 598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // For simplicity we always test the accumulator register. 599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Drop(count); 600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(result_register(), reg); 601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); 602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->DoTest(this); 603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EffectContext::Plug(Label* materialize_true, 607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* materialize_false) const { 608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(materialize_true == materialize_false); 609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(materialize_true); 610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::AccumulatorValueContext::Plug( 614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* materialize_true, 615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* materialize_false) const { 616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(materialize_true); 618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(result_register(), Heap::kTrueValueRootIndex); 619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(materialize_false); 621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(result_register(), Heap::kFalseValueRootIndex); 622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::StackValueContext::Plug( 627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* materialize_true, 628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* materialize_false) const { 629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(materialize_true); 631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x10, Heap::kTrueValueRootIndex); 632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(materialize_false); 634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x10, Heap::kFalseValueRootIndex); 635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x10); 637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::TestContext::Plug(Label* materialize_true, 641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* materialize_false) const { 642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(materialize_true == true_label_); 643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(materialize_false == false_label_); 644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EffectContext::Plug(bool flag) const { 648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { 652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::RootListIndex value_root_index = 653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(result_register(), value_root_index); 655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::StackValueContext::Plug(bool flag) const { 659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::RootListIndex value_root_index = 660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x10, value_root_index); 662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x10); 663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::TestContext::Plug(bool flag) const { 667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), 668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch true, 669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch true_label_, 670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch false_label_); 671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (flag) { 672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (true_label_ != fall_through_) { 673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(true_label_); 674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (false_label_ != fall_through_) { 677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(false_label_); 678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::DoTest(Expression* condition, 684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true, 685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false, 686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through) { 687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); 688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, condition->test_id()); 689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareAndSplit(result_register(), 0, ne, if_true, if_false, fall_through); 690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// If (cond), branch to if_true. 694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// If (!cond), branch to if_false. 695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// fall_through is used as an optimization in cases where only one branch 696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// instruction is necessary. 697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::Split(Condition cond, 698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true, 699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false, 700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through) { 701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (if_false == fall_through) { 702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(cond, if_true); 703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (if_true == fall_through) { 704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(if_false != fall_through); 705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(NegateCondition(cond), if_false); 706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(cond, if_true); 708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(if_false); 709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMemOperand FullCodeGenerator::StackOperand(Variable* var) { 714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Offset is negative because higher indexes are at lower addresses. 715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = -var->index() * kXRegSize; 716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Adjust by a (parameter or local) base offset. 717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->IsParameter()) { 718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch offset += (info_->scope()->num_parameters() + 1) * kPointerSize; 719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch offset += JavaScriptFrameConstants::kLocal0Offset; 721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return MemOperand(fp, offset); 723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) { 727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsContextSlot() || var->IsStackAllocated()); 728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->IsContextSlot()) { 729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int context_chain_length = scope()->ContextChainLength(var->scope()); 730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadContext(scratch, context_chain_length); 731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return ContextMemOperand(scratch, var->index()); 732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return StackOperand(var); 734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::GetVar(Register dest, Variable* var) { 739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Use destination as scratch. 740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand location = VarOperand(var, dest); 741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(dest, location); 742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::SetVar(Variable* var, 746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register src, 747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch0, 748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1) { 749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsContextSlot() || var->IsStackAllocated()); 750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!AreAliased(src, scratch0, scratch1)); 751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand location = VarOperand(var, scratch0); 752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(src, location); 753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit the write barrier code if the location is in the heap. 755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->IsContextSlot()) { 756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // scratch0 contains the correct context. 757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteContextSlot(scratch0, 758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch location.offset(), 759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch src, 760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scratch1, 761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kLRHasBeenSaved, 762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kDontSaveFPRegs); 763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr, 768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool should_normalize, 769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true, 770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false) { 771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Only prepare for bailouts before splits if we're in a test 772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // context. Otherwise, we let the Visit function deal with the 773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // preparation to avoid preparing with the same AST id twice. 774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!context()->IsTest() || !info_->IsOptimizable()) return; 775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(all): Investigate to see if there is something to work on here. 777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label skip; 778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (should_normalize) { 779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&skip); 780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailout(expr, TOS_REG); 782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (should_normalize) { 783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(x0, Heap::kTrueValueRootIndex); 784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(eq, if_true, if_false, NULL); 785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&skip); 786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) { 791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The variable in the declaration always resides in the current function 792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // context. 793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0, scope()->ContextChainLength(variable->scope())); 794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (generate_debug_code_) { 795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that we're not inside a with or catch context. 796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x1, FieldMemOperand(cp, HeapObject::kMapOffset)); 797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(x1, Heap::kWithContextMapRootIndex); 798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(ne, kDeclarationInWithContext); 799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(x1, Heap::kCatchContextMapRootIndex); 800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(ne, kDeclarationInCatchContext); 801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitVariableDeclaration( 806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableDeclaration* declaration) { 807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If it was not possible to allocate the variable at compile time, we 808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // need to "declare" it at runtime to make sure it actually exists in the 809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // local context. 810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableProxy* proxy = declaration->proxy(); 811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableMode mode = declaration->mode(); 812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* variable = proxy->var(); 813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY; 814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (variable->location()) { 816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::UNALLOCATED: 817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch globals_->Add(variable->name(), zone()); 818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch globals_->Add(variable->binding_needs_init() 819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? isolate()->factory()->the_hole_value() 820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : isolate()->factory()->undefined_value(), 821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch zone()); 822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::PARAMETER: 825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::LOCAL: 826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hole_init) { 827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ VariableDeclaration"); 828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x10, Heap::kTheHoleValueRootIndex); 829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(x10, StackOperand(variable)); 830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::CONTEXT: 834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hole_init) { 835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ VariableDeclaration"); 836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitDebugCheckDeclarationContext(variable); 837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x10, Heap::kTheHoleValueRootIndex); 838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(x10, ContextMemOperand(cp, variable->index())); 839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // No write barrier since the_hole_value is in old space. 840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(proxy->id(), NO_REGISTERS); 841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::LOOKUP: { 845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ VariableDeclaration"); 846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x2, Operand(variable->name())); 847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Declaration nodes are always introduced in one of four modes. 848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsDeclaredVariableMode(mode)); 849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PropertyAttributes attr = IsImmutableVariableMode(mode) ? READ_ONLY 850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : NONE; 851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x1, Smi::FromInt(attr)); 852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push initial value, if any. 853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Note: For variables we must not push an initial value (such as 854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 'undefined') because we may have a (legal) redeclaration and we 855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // must not destroy the current value. 856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hole_init) { 857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x0, Heap::kTheHoleValueRootIndex); 858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(cp, x2, x1, x0); 859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pushing 0 (xzr) indicates no initial value. 861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(cp, x2, x1, xzr); 862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kDeclareLookupSlot, 4); 864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitFunctionDeclaration( 871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FunctionDeclaration* declaration) { 872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableProxy* proxy = declaration->proxy(); 873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* variable = proxy->var(); 874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (variable->location()) { 875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::UNALLOCATED: { 876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch globals_->Add(variable->name(), zone()); 877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<SharedFunctionInfo> function = 878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Compiler::BuildFunctionInfo(declaration->fun(), script(), info_); 879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for stack overflow exception. 880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (function.is_null()) return SetStackOverflow(); 881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch globals_->Add(function, zone()); 882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::PARAMETER: 886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::LOCAL: { 887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Function Declaration"); 888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(declaration->fun()); 889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(result_register(), StackOperand(variable)); 890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::CONTEXT: { 894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Function Declaration"); 895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitDebugCheckDeclarationContext(variable); 896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(declaration->fun()); 897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(result_register(), ContextMemOperand(cp, variable->index())); 898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = Context::SlotOffset(variable->index()); 899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We know that we have written a function, which is not a smi. 900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteContextSlot(cp, 901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch offset, 902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result_register(), 903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x2, 904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kLRHasBeenSaved, 905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kDontSaveFPRegs, 906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EMIT_REMEMBERED_SET, 907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OMIT_SMI_CHECK); 908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(proxy->id(), NO_REGISTERS); 909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::LOOKUP: { 913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Function Declaration"); 914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x2, Operand(variable->name())); 915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x1, Smi::FromInt(NONE)); 916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(cp, x2, x1); 917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push initial value for function declaration. 918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(declaration->fun()); 919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kDeclareLookupSlot, 4); 920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { 927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* variable = declaration->proxy()->var(); 928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(variable->location() == Variable::CONTEXT); 929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(variable->interface()->IsFrozen()); 930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ ModuleDeclaration"); 932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitDebugCheckDeclarationContext(variable); 933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load instance object. 935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadContext(x1, scope_->ContextChainLength(scope_->GlobalScope())); 936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x1, ContextMemOperand(x1, variable->interface()->Index())); 937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x1, ContextMemOperand(x1, Context::EXTENSION_INDEX)); 938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Assign it. 940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(x1, ContextMemOperand(cp, variable->index())); 941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We know that we have written a module, which is not a smi. 942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteContextSlot(cp, 943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Context::SlotOffset(variable->index()), 944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x1, 945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x3, 946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kLRHasBeenSaved, 947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kDontSaveFPRegs, 948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EMIT_REMEMBERED_SET, 949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OMIT_SMI_CHECK); 950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(declaration->proxy()->id(), NO_REGISTERS); 951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Traverse info body. 953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Visit(declaration->module()); 954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) { 958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableProxy* proxy = declaration->proxy(); 959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* variable = proxy->var(); 960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (variable->location()) { 961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::UNALLOCATED: 962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(rossberg) 963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::CONTEXT: { 966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ ImportDeclaration"); 967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitDebugCheckDeclarationContext(variable); 968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(rossberg) 969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::PARAMETER: 973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::LOCAL: 974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::LOOKUP: 975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) { 981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(rossberg) 982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the runtime to declare the globals. 987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x11, Operand(pairs)); 988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register flags = xzr; 989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (Smi::FromInt(DeclareGlobalsFlags())) { 990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch flags = x10; 991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(flags, Smi::FromInt(DeclareGlobalsFlags())); 992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(cp, x11, flags); 994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kDeclareGlobals, 3); 995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return value is ignored. 996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { 1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the runtime to declare the modules. 1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(descriptions); 1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kDeclareModules, 1); 1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return value is ignored. 1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::VisitSwitchStatement"); 1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ SwitchStatement"); 1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Breakable nested_statement(this, stmt); 1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetStatementPosition(stmt); 1012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Keep the switch value on the stack until a case matches. 1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(stmt->tag()); 1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); 1016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<CaseClause*>* clauses = stmt->cases(); 1018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CaseClause* default_clause = NULL; // Can occur anywhere in the list. 1019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label next_test; // Recycled for each test. 1021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compile all the tests with branches to their bodies. 1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < clauses->length(); i++) { 1023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CaseClause* clause = clauses->at(i); 1024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch clause->body_target()->Unuse(); 1025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The default is not a test, but remember it as final fall through. 1027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (clause->is_default()) { 1028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default_clause = clause; 1029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch continue; 1030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Case comparison"); 1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&next_test); 1034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch next_test.Unuse(); 1035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compile the label expression. 1037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(clause->label()); 1038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform the comparison as if via '==='. 1040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(x1, 0); // Switch value. 1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JumpPatchSite patch_site(masm_); 1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (ShouldInlineSmiCase(Token::EQ_STRICT)) { 1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow_case; 1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patch_site.EmitJumpIfEitherNotSmi(x0, x1, &slow_case); 1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(x1, x0); 1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(ne, &next_test); 1048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Drop(1); // Switch value is no longer needed. 1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(clause->body_target()); 1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&slow_case); 1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record position before stub call for type feedback. 1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetSourcePosition(clause->position()); 1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = 1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code(); 1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, clause->CompareId()); 1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patch_site.EmitPatchInfo(); 1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label skip; 1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&skip); 1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailout(clause, TOS_REG); 1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotRoot(x0, Heap::kTrueValueRootIndex, &next_test); 1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Drop(1); 1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(clause->body_target()); 1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&skip); 1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cbnz(x0, &next_test); 1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Drop(1); // Switch value is no longer needed. 1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(clause->body_target()); 1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Discard the test value and jump to the default if present, otherwise to 1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the end of the statement. 1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&next_test); 1076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Drop(1); // Switch value is no longer needed. 1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (default_clause == NULL) { 1078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(nested_statement.break_label()); 1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(default_clause->body_target()); 1081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compile all the case bodies. 1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < clauses->length(); i++) { 1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Case body"); 1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CaseClause* clause = clauses->at(i); 1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(clause->body_target()); 1088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS); 1089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitStatements(clause->statements()); 1090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(nested_statement.break_label()); 1093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 1094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { 1098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::VisitForInStatement"); 1099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ ForInStatement"); 1100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int slot = stmt->ForInFeedbackSlot(); 1101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(all): This visitor probably needs better comments and a revisit. 1102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetStatementPosition(stmt); 1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label loop, exit; 1105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ForIn loop_statement(this, stmt); 1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch increment_loop_depth(); 1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the object to enumerate over. If the object is null or undefined, skip 1109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // over the loop. See ECMA-262 version 5, section 12.6.4. 1110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(stmt->enumerable()); 1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfRoot(x0, Heap::kUndefinedValueRootIndex, &exit); 1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register null_value = x15; 1113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(null_value, Heap::kNullValueRootIndex); 1114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(x0, null_value); 1115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(eq, &exit); 1116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(stmt->PrepareId(), TOS_REG); 1118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Convert the object to a JS object. 1120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label convert, done_convert; 1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x0, &convert); 1122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfObjectType(x0, x10, x11, FIRST_SPEC_OBJECT_TYPE, &done_convert, ge); 1123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&convert); 1124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); 1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 1126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done_convert); 1127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); 1128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for proxies. 1130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label call_runtime; 1131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 1132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfObjectType(x0, x10, x11, LAST_JS_PROXY_TYPE, &call_runtime, le); 1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check cache validity in generated code. This is a fast case for 1135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the JSObject::IsSimpleEnum cache validity checks. If we cannot 1136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // guarantee cache validity, call the runtime system to check cache 1137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // validity or get the property names in a fixed array. 1138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CheckEnumCache(x0, null_value, x10, x11, x12, x13, &call_runtime); 1139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The enum cache is valid. Load the map of the object being 1141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // iterated over and use the cache for the iteration. 1142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label use_cache; 1143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x0, FieldMemOperand(x0, HeapObject::kMapOffset)); 1144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&use_cache); 1145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the set of properties to enumerate. 1147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&call_runtime); 1148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); // Duplicate the enumerable object on the stack. 1149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); 1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we got a map from the runtime call, we can do a fast 1152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // modification check. Otherwise, we got a fixed array, and we have 1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to do a slow check. 1154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label fixed_array, no_descriptors; 1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x2, FieldMemOperand(x0, HeapObject::kMapOffset)); 1156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotRoot(x2, Heap::kMetaMapRootIndex, &fixed_array); 1157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We got a map in register x0. Get the enumeration cache from it. 1159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&use_cache); 1160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ EnumLengthUntagged(x1, x0); 1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cbz(x1, &no_descriptors); 1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadInstanceDescriptors(x0, x2); 1165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x2, FieldMemOperand(x2, DescriptorArray::kEnumCacheOffset)); 1166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x2, 1167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldMemOperand(x2, DescriptorArray::kEnumCacheBridgeCacheOffset)); 1168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Set up the four remaining stack slots. 1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(x1); 1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Map, enumeration cache, enum cache length, zero (both last as smis). 1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0, x2, x1, xzr); 1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&loop); 1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&no_descriptors); 1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Drop(1); 1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&exit); 1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We got a fixed array in register x0. Iterate through that. 1180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&fixed_array); 1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadObject(x1, FeedbackVector()); 1183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x10, Operand(TypeFeedbackVector::MegamorphicSentinel(isolate()))); 1184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(x10, FieldMemOperand(x1, FixedArray::OffsetOfElementAt(slot))); 1185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x1, Smi::FromInt(1)); // Smi indicates slow check. 1187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(x10, 0); // Get enumerated object. 1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(all): similar check was done already. Can we avoid it here? 1190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareObjectType(x10, x11, x12, LAST_JS_PROXY_TYPE); 1191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Smi::FromInt(0) == 0); 1192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CzeroX(x1, le); // Zero indicates proxy. 1193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x2, FieldMemOperand(x0, FixedArray::kLengthOffset)); 1194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Smi and array, fixed array length (as smi) and initial index. 1195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x1, x0, x2, xzr); 1196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generate code for doing the condition check. 1198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); 1199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&loop); 1200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the current count to x0, load the length to x1. 1201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PeekPair(x0, x1, 0); 1202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(x0, x1); // Compare to the array length. 1203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(hs, loop_statement.break_label()); 1204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the current entry of the array into register r3. 1206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(x10, 2 * kXRegSize); 1207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Add(x10, x10, Operand::UntagSmiAndScale(x0, kPointerSizeLog2)); 1208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x3, MemOperand(x10, FixedArray::kHeaderSize - kHeapObjectTag)); 1209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the expected map from the stack or a smi in the 1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // permanent slow case into register x10. 1212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(x2, 3 * kXRegSize); 1213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if the expected map still matches that of the enumerable. 1215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If not, we may have to filter the key. 1216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label update_each; 1217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(x1, 4 * kXRegSize); 1218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x11, FieldMemOperand(x1, HeapObject::kMapOffset)); 1219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(x11, x2); 1220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(eq, &update_each); 1221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // For proxies, no filtering is done. 1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(rossberg): What if only a prototype is a proxy? Not specified yet. 1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cbz(x2, &update_each); 1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Convert the entry to a string or (smi) 0 if it isn't a property 1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // any more. If the property has been removed while iterating, we 1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // just skip it. 1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x1, x3); 1231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); 1232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x3, x0); 1233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cbz(x0, loop_statement.continue_label()); 1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update the 'each' property or variable from the possibly filtered 1236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // entry in register x3. 1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&update_each); 1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(result_register(), x3); 1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform the assignment as if via '='. 1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { EffectContext context(this); 1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitAssignment(stmt->each()); 1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generate code for the body of the loop. 1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Visit(stmt->body()); 1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generate code for going to the next element by incrementing 1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the index (smi) stored on top of the stack. 1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(loop_statement.continue_label()); 1250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(all): We could use a callee saved register to avoid popping. 1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(x0); 1252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Add(x0, x0, Smi::FromInt(1)); 1253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); 1254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBackEdgeBookkeeping(stmt, &loop); 1256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&loop); 1257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Remove the pointers stored on the stack. 1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(loop_statement.break_label()); 1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Drop(5); 1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Exit and decrement the loop depth. 1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&exit); 1265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch decrement_loop_depth(); 1266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { 1270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ ForOfStatement"); 1271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetStatementPosition(stmt); 1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Iteration loop_statement(this, stmt); 1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch increment_loop_depth(); 1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // var iterator = iterable[Symbol.iterator](); 1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForEffect(stmt->assign_iterator()); 1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Loop entry. 1280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(loop_statement.continue_label()); 1281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // result = iterator.next() 1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForEffect(stmt->next_result()); 1284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // if (result.done) break; 1286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label result_not_done; 1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForControl(stmt->result_done(), 1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch loop_statement.break_label(), 1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &result_not_done, 1290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &result_not_done); 1291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&result_not_done); 1292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // each = result.value 1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForEffect(stmt->assign_each()); 1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generate code for the body of the loop. 1297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Visit(stmt->body()); 1298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check stack before looping. 1300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS); 1301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label()); 1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(loop_statement.continue_label()); 1303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Exit and decrement the loop depth. 1305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(loop_statement.break_label()); 1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch decrement_loop_depth(); 1308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, 1312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool pretenure) { 1313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Use the fast case closure allocation code that allocates in new space for 1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // nested functions that don't need literals cloning. If we're running with 1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the --always-opt or the --prepare-always-opt flag, we need to use the 1316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // runtime function so that the new function we are creating here gets a 1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // chance to have its code optimized and doesn't just get a copy of the 1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // existing unoptimized code. 1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!FLAG_always_opt && 1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !FLAG_prepare_always_opt && 1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !pretenure && 1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scope()->is_function_scope() && 1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info->num_literals() == 0) { 1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind()); 1325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x2, Operand(info)); 1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallStub(&stub); 1327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x11, Operand(info)); 1329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x10, pretenure ? Heap::kTrueValueRootIndex 1330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : Heap::kFalseValueRootIndex); 1331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(cp, x11, x10); 1332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kNewClosure, 3); 1333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 1339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ VariableProxy"); 1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitVariableLoad(expr); 1341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) { 1345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cnmt(masm_, "[ SuperReference "); 1346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(LoadDescriptor::ReceiverRegister(), 1348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 1349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol()); 1351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(LoadDescriptor::NameRegister(), Operand(home_object_symbol)); 1352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId()); 1354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x10, Operand(isolate()->factory()->undefined_value())); 1356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(x0, x10); 1357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 1358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(&done, ne); 1359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kThrowNonMethodError, 0); 1360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, 1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TypeofState typeof_state, 1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* slow) { 1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register current = cp; 1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register next = x10; 1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp = x11; 1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Scope* s = scope(); 1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (s != NULL) { 1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (s->num_heap_slots() > 0) { 1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (s->calls_sloppy_eval()) { 1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that extension is NULL. 1376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(temp, ContextMemOperand(current, Context::EXTENSION_INDEX)); 1377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cbnz(temp, slow); 1378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load next context in chain. 1380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(next, ContextMemOperand(current, Context::PREVIOUS_INDEX)); 1381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Walk the rest of the chain without clobbering cp. 1382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch current = next; 1383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If no outer scope calls eval, we do not need to check more 1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // context extensions. 1386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!s->outer_scope_calls_sloppy_eval() || s->is_eval_scope()) break; 1387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch s = s->outer_scope(); 1388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (s->is_eval_scope()) { 1391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label loop, fast; 1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(next, current); 1393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&loop); 1395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Terminate at native context. 1396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(temp, FieldMemOperand(next, HeapObject::kMapOffset)); 1397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfRoot(temp, Heap::kNativeContextMapRootIndex, &fast); 1398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that extension is NULL. 1399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(temp, ContextMemOperand(next, Context::EXTENSION_INDEX)); 1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cbnz(temp, slow); 1401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load next context in chain. 1402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(next, ContextMemOperand(next, Context::PREVIOUS_INDEX)); 1403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&loop); 1404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&fast); 1405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectMemOperand()); 1408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(LoadDescriptor::NameRegister(), Operand(proxy->var()->name())); 1409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(VectorLoadICDescriptor::SlotRegister(), 1411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(proxy->VariableFeedbackSlot())); 1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ContextualMode mode = (typeof_state == INSIDE_TYPEOF) ? NOT_CONTEXTUAL 1415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : CONTEXTUAL; 1416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(mode); 1417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, 1421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* slow) { 1422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsContextSlot()); 1423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register context = cp; 1424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register next = x10; 1425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp = x11; 1426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { 1428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (s->num_heap_slots() > 0) { 1429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (s->calls_sloppy_eval()) { 1430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that extension is NULL. 1431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(temp, ContextMemOperand(context, Context::EXTENSION_INDEX)); 1432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cbnz(temp, slow); 1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(next, ContextMemOperand(context, Context::PREVIOUS_INDEX)); 1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Walk the rest of the chain without clobbering cp. 1436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context = next; 1437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that last extension is NULL. 1440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(temp, ContextMemOperand(context, Context::EXTENSION_INDEX)); 1441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cbnz(temp, slow); 1442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This function is used only for loads, not stores, so it's safe to 1444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // return an cp-based operand (the write barrier cannot be allowed to 1445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // destroy the cp register). 1446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return ContextMemOperand(context, var->index()); 1447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy, 1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TypeofState typeof_state, 1452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* slow, 1453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* done) { 1454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generate fast-case code for variables that might be shadowed by 1455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // eval-introduced variables. Eval is used a lot without 1456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // introducing variables. In those cases, we do not want to 1457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // perform a runtime call for all variables in the scope 1458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // containing the eval. 1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* var = proxy->var(); 1460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->mode() == DYNAMIC_GLOBAL) { 1461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitLoadGlobalCheckExtensions(proxy, typeof_state, slow); 1462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(done); 1463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (var->mode() == DYNAMIC_LOCAL) { 1464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* local = var->local_if_not_shadowed(); 1465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x0, ContextSlotOperandCheckExtensions(local, slow)); 1466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (local->mode() == LET || local->mode() == CONST || 1467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch local->mode() == CONST_LEGACY) { 1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, done); 1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (local->mode() == CONST_LEGACY) { 1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); 1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { // LET || CONST 1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x0, Operand(var->name())); 1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); 1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kThrowReferenceError, 1); 1475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(done); 1478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { 1483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record position before possible IC call. 1484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetSourcePosition(proxy->position()); 1485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* var = proxy->var(); 1486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Three cases: global variables, lookup variables, and all other types of 1488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // variables. 1489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (var->location()) { 1490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::UNALLOCATED: { 1491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "Global variable"); 1492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectMemOperand()); 1493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(LoadDescriptor::NameRegister(), Operand(var->name())); 1494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 1495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(VectorLoadICDescriptor::SlotRegister(), 1496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(proxy->VariableFeedbackSlot())); 1497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(CONTEXTUAL); 1499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 1500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::PARAMETER: 1504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::LOCAL: 1505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::CONTEXT: { 1506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, var->IsContextSlot() 1507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? "Context variable" 1508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : "Stack variable"); 1509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->binding_needs_init()) { 1510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // var->scope() may be NULL when the proxy is located in eval code and 1511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // refers to a potential outside binding. Currently those bindings are 1512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // always looked up dynamically, i.e. in that case 1513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // var->location() == LOOKUP. 1514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // always holds. 1515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->scope() != NULL); 1516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if the binding really needs an initialization check. The check 1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // can be skipped in the following situation: we have a LET or CONST 1519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // binding in harmony mode, both the Variable and the VariableProxy have 1520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the same declaration scope (i.e. they are both in global code, in the 1521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // same function or in the same eval code) and the VariableProxy is in 1522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the source physically located after the initializer of the variable. 1523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 1524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We cannot skip any initialization checks for CONST in non-harmony 1525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // mode because const variables may be declared but never initialized: 1526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // if (false) { const x; }; var y = x; 1527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 1528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The condition on the declaration scopes is a conservative check for 1529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // nested functions that access a binding and are called before the 1530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // binding is initialized: 1531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // function() { f(); let x = 1; function f() { x = 2; } } 1532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 1533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool skip_init_check; 1534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) { 1535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch skip_init_check = false; 1536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that we always have valid source position. 1538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->initializer_position() != RelocInfo::kNoPosition); 1539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(proxy->position() != RelocInfo::kNoPosition); 1540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch skip_init_check = var->mode() != CONST_LEGACY && 1541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch var->initializer_position() < proxy->position(); 1542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!skip_init_check) { 1545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Let and const need a read barrier. 1546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GetVar(x0, var); 1547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 1548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, &done); 1549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->mode() == LET || var->mode() == CONST) { 1550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Throw a reference error when using an uninitialized let/const 1551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // binding in harmony mode. 1552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x0, Operand(var->name())); 1553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); 1554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kThrowReferenceError, 1); 1555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Uninitalized const bindings outside of harmony mode are unholed. 1558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->mode() == CONST_LEGACY); 1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); 1560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 1561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 1563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(var); 1567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::LOOKUP: { 1571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done, slow; 1572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generate code for loading from variables potentially shadowed by 1573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // eval-introduced variables. 1574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done); 1575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&slow); 1576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "Lookup variable"); 1577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x1, Operand(var->name())); 1578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(cp, x1); // Context and name. 1579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kLoadLookupSlot, 2); 1580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 1581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 1582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 1589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ RegExpLiteral"); 1590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialized; 1591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Registers will be used as follows: 1592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // x5 = materialized value (RegExp literal) 1593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // x4 = JS function, literals array 1594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // x3 = literal index 1595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // x2 = RegExp pattern 1596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // x1 = RegExp flags 1597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // x0 = RegExp literal clone 1598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x10, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 1599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x4, FieldMemOperand(x10, JSFunction::kLiteralsOffset)); 1600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int literal_offset = 1601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; 1602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x5, FieldMemOperand(x4, literal_offset)); 1603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotRoot(x5, Heap::kUndefinedValueRootIndex, &materialized); 1604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Create regexp literal using runtime function. 1606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Result will be in x0. 1607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x3, Smi::FromInt(expr->literal_index())); 1608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x2, Operand(expr->pattern())); 1609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x1, Operand(expr->flags())); 1610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x4, x3, x2, x1); 1611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 1612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x5, x0); 1613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&materialized); 1615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; 1616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label allocated, runtime_allocate; 1617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Allocate(size, x0, x2, x3, &runtime_allocate, TAG_OBJECT); 1618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&allocated); 1619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&runtime_allocate); 1621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x10, Smi::FromInt(size)); 1622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x5, x10); 1623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kAllocateInNewSpace, 1); 1624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(x5); 1625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&allocated); 1627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // After this, registers are used as follows: 1628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // x0: Newly allocated regexp. 1629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // x5: Materialized regexp. 1630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // x10, x11, x12: temps. 1631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CopyFields(x0, x5, CPURegList(x10, x11, x12), size / kPointerSize); 1632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 1633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitAccessor(Expression* expression) { 1637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expression == NULL) { 1638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x10, Heap::kNullValueRootIndex); 1639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x10); 1640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(expression); 1642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 1647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ ObjectLiteral"); 1648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch expr->BuildConstantProperties(isolate()); 1650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<FixedArray> constant_properties = expr->constant_properties(); 1651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 1652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x3, FieldMemOperand(x3, JSFunction::kLiteralsOffset)); 1653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x2, Smi::FromInt(expr->literal_index())); 1654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x1, Operand(constant_properties)); 1655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int flags = expr->fast_elements() 1656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? ObjectLiteral::kFastElements 1657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : ObjectLiteral::kNoFlags; 1658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch flags |= expr->has_function() 1659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? ObjectLiteral::kHasFunction 1660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : ObjectLiteral::kNoFlags; 1661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x0, Smi::FromInt(flags)); 1662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int properties_count = constant_properties->length() / 2; 1663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int max_cloned_properties = 1664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FastCloneShallowObjectStub::kMaximumClonedProperties; 1665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->may_store_doubles() || expr->depth() > 1 || 1666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm()->serializer_enabled() || flags != ObjectLiteral::kFastElements || 1667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch properties_count > max_cloned_properties) { 1668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x3, x2, x1, x0); 1669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kCreateObjectLiteral, 4); 1670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FastCloneShallowObjectStub stub(isolate(), properties_count); 1672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallStub(&stub); 1673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If result_saved is true the result is on top of the stack. If 1676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // result_saved is false the result is in x0. 1677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool result_saved = false; 1678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Mark all computed expressions that are bound to a key that 1680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is shadowed by a later occurrence of the same key. For the 1681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // marked expressions, no store code is emitted. 1682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch expr->CalculateEmitStore(zone()); 1683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AccessorTable accessor_table(zone()); 1685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < expr->properties()->length(); i++) { 1686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ObjectLiteral::Property* property = expr->properties()->at(i); 1687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (property->IsCompileTimeValue()) continue; 1688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Literal* key = property->key(); 1690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* value = property->value(); 1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!result_saved) { 1692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); // Save result on stack 1693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result_saved = true; 1694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (property->kind()) { 1696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case ObjectLiteral::Property::CONSTANT: 1697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 1698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); 1700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Fall through. 1701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case ObjectLiteral::Property::COMPUTED: 1702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (key->value()->IsInternalizedString()) { 1703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (property->emit_store()) { 1704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(value); 1705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(StoreDescriptor::ValueRegister().is(x0)); 1706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(StoreDescriptor::NameRegister(), Operand(key->value())); 1707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(StoreDescriptor::ReceiverRegister(), 0); 1708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallStoreIC(key->LiteralFeedbackId()); 1709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(key->id(), NO_REGISTERS); 1710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForEffect(value); 1712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (property->emit_store()) { 1716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Duplicate receiver on stack. 1717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(x0, 0); 1718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); 1719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(key); 1720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(value); 1721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x0, Smi::FromInt(SLOPPY)); // Strict mode 1722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); 1723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kSetProperty, 4); 1724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForEffect(key); 1726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForEffect(value); 1727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case ObjectLiteral::Property::PROTOTYPE: 1730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (property->emit_store()) { 1731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Duplicate receiver on stack. 1732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(x0, 0); 1733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); 1734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(value); 1735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kSetPrototype, 2); 1736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForEffect(value); 1738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case ObjectLiteral::Property::GETTER: 1741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch accessor_table.lookup(key)->second->getter = value; 1742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case ObjectLiteral::Property::SETTER: 1744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch accessor_table.lookup(key)->second->setter = value; 1745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit code to define accessors, using only a single call to the runtime for 1750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // each pair of corresponding getters and setters. 1751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (AccessorTable::Iterator it = accessor_table.begin(); 1752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch it != accessor_table.end(); 1753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++it) { 1754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(x10, 0); // Duplicate receiver. 1755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x10); 1756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(it->first); 1757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitAccessor(it->second->getter); 1758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitAccessor(it->second->setter); 1759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x10, Smi::FromInt(NONE)); 1760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x10); 1761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); 1762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->has_function()) { 1765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(result_saved); 1766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(x0, 0); 1767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); 1768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kToFastProperties, 1); 1769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (result_saved) { 1772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PlugTOS(); 1773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 1775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 1780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ ArrayLiteral"); 1781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch expr->BuildConstantElements(isolate()); 1783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int flags = (expr->depth() == 1) ? ArrayLiteral::kShallowElements 1784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : ArrayLiteral::kNoFlags; 1785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* subexprs = expr->values(); 1787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int length = subexprs->length(); 1788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<FixedArray> constant_elements = expr->constant_elements(); 1789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(2, constant_elements->length()); 1790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ElementsKind constant_elements_kind = 1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); 1792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool has_fast_elements = IsFastObjectElementsKind(constant_elements_kind); 1793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<FixedArrayBase> constant_elements_values( 1794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FixedArrayBase::cast(constant_elements->get(1))); 1795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE; 1797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (has_fast_elements && !FLAG_allocation_site_pretenuring) { 1798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the only customer of allocation sites is transitioning, then 1799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // we can turn it off if we don't have anywhere else to transition to. 1800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; 1801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 1804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x3, FieldMemOperand(x3, JSFunction::kLiteralsOffset)); 1805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x2, Smi::FromInt(expr->literal_index())); 1806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x1, Operand(constant_elements)); 1807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) { 1808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x0, Smi::FromInt(flags)); 1809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x3, x2, x1, x0); 1810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kCreateArrayLiteral, 4); 1811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); 1813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallStub(&stub); 1814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool result_saved = false; // Is the result saved to the stack? 1817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit code to evaluate all the non-constant subexpressions and to store 1819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // them into the newly cloned array. 1820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < length; i++) { 1821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* subexpr = subexprs->at(i); 1822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the subexpression is a literal or a simple materialized literal it 1823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is already set in the cloned array. 1824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; 1825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!result_saved) { 1827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x1, Smi::FromInt(expr->literal_index())); 1828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0, x1); 1829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result_saved = true; 1830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(subexpr); 1832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsFastObjectElementsKind(constant_elements_kind)) { 1834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = FixedArray::kHeaderSize + (i * kPointerSize); 1835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(x6, kPointerSize); // Copy of array literal. 1836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x1, FieldMemOperand(x6, JSObject::kElementsOffset)); 1837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(result_register(), FieldMemOperand(x1, offset)); 1838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update the write barrier for the array store. 1839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteField(x1, offset, result_register(), x10, 1840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kLRHasBeenSaved, kDontSaveFPRegs, 1841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EMIT_REMEMBERED_SET, INLINE_SMI_CHECK); 1842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x3, Smi::FromInt(i)); 1844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StoreArrayLiteralElementStub stub(isolate()); 1845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallStub(&stub); 1846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); 1849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (result_saved) { 1852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Drop(1); // literal index 1853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PlugTOS(); 1854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 1856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitAssignment(Assignment* expr) { 1861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->target()->IsValidReferenceExpression()); 1862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Assignment"); 1864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Left-hand side can only be a property, a global or a (parameter or local) 1866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // slot. 1867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LhsKind assign_type = VARIABLE; 1869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Property* property = expr->target()->AsProperty(); 1870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (property != NULL) { 1871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assign_type = (property->key()->IsPropertyName()) 1872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? NAMED_PROPERTY 1873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : KEYED_PROPERTY; 1874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Evaluate LHS expression. 1877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (assign_type) { 1878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case VARIABLE: 1879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Nothing to do here. 1880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case NAMED_PROPERTY: 1882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->is_compound()) { 1883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We need the receiver both on the stack and in the register. 1884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(property->obj()); 1885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(LoadDescriptor::ReceiverRegister(), 0); 1886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(property->obj()); 1888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case KEYED_PROPERTY: 1891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->is_compound()) { 1892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(property->obj()); 1893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(property->key()); 1894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(LoadDescriptor::ReceiverRegister(), 1 * kPointerSize); 1895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(LoadDescriptor::NameRegister(), 0); 1896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(property->obj()); 1898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(property->key()); 1899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // For compound assignments we need another deoptimization point after the 1904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // variable/property load. 1905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->is_compound()) { 1906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { AccumulatorValueContext context(this); 1907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (assign_type) { 1908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case VARIABLE: 1909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitVariableLoad(expr->target()->AsVariableProxy()); 1910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailout(expr->target(), TOS_REG); 1911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case NAMED_PROPERTY: 1913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitNamedPropertyLoad(property); 1914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(property->LoadId(), TOS_REG); 1915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case KEYED_PROPERTY: 1917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitKeyedPropertyLoad(property); 1918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(property->LoadId(), TOS_REG); 1919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Token::Value op = expr->binary_op(); 1924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); // Left operand goes on the stack. 1925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(expr->value()); 1926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OverwriteMode mode = expr->value()->ResultOverwriteAllowed() 1928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? OVERWRITE_RIGHT 1929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : NO_OVERWRITE; 1930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetSourcePosition(expr->position() + 1); 1931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AccumulatorValueContext context(this); 1932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (ShouldInlineSmiCase(op)) { 1933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitInlineSmiBinaryOp(expr->binary_operation(), 1934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch op, 1935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mode, 1936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch expr->target(), 1937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch expr->value()); 1938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBinaryOp(expr->binary_operation(), op, mode); 1940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Deoptimization point in case the binary operation may have side effects. 1943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailout(expr->binary_operation(), TOS_REG); 1944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(expr->value()); 1946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record source position before possible IC call. 1949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetSourcePosition(expr->position()); 1950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store the value. 1952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (assign_type) { 1953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case VARIABLE: 1954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), 1955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch expr->op()); 1956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 1957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 1958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case NAMED_PROPERTY: 1960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitNamedPropertyAssignment(expr); 1961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case KEYED_PROPERTY: 1963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitKeyedPropertyAssignment(expr); 1964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { 1970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetSourcePosition(prop->position()); 1971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Literal* key = prop->key()->AsLiteral(); 1972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!prop->IsSuperAccess()); 1973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(LoadDescriptor::NameRegister(), Operand(key->value())); 1975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 1976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(VectorLoadICDescriptor::SlotRegister(), 1977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(prop->PropertyFeedbackSlot())); 1978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(NOT_CONTEXTUAL); 1979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); 1981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) { 1986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetSourcePosition(prop->position()); 1987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Literal* key = prop->key()->AsLiteral(); 1988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!key->value()->IsSmi()); 1989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(prop->IsSuperAccess()); 1990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SuperReference* super_ref = prop->obj()->AsSuperReference(); 1992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitLoadHomeObject(super_ref); 1993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); 1994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(super_ref->this_var()); 1995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(key->value()); 1996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kLoadFromSuper, 3); 1997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { 2001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetSourcePosition(prop->position()); 2002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call keyed load IC. It has arguments key and receiver in r0 and r1. 2003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code(); 2004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 2005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(VectorLoadICDescriptor::SlotRegister(), 2006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(prop->PropertyFeedbackSlot())); 2007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic); 2008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, prop->PropertyFeedbackId()); 2010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, 2015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Token::Value op, 2016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OverwriteMode mode, 2017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* left_expr, 2018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* right_expr) { 2019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done, both_smis, stub_call; 2020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the arguments. 2022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register left = x1; 2023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register right = x0; 2024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = x0; 2025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(left); 2026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform combined smi check on both operands. 2028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Orr(x10, left, right); 2029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JumpPatchSite patch_site(masm_); 2030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patch_site.EmitJumpIfSmi(x10, &both_smis); 2031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&stub_call); 2033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op, mode).code(); 2035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 2036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::BlockPoolsScope scope(masm_); 2037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(code, expr->BinaryOperationFeedbackId()); 2038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patch_site.EmitPatchInfo(); 2039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 2041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&both_smis); 2043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Smi case. This code works in the same way as the smi-smi case in the type 2044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // recording binary operation stub, see 2045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // BinaryOpStub::GenerateSmiSmiOperation for comments. 2046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(all): That doesn't exist any more. Where are the comments? 2047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 2048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The set of operations that needs to be supported here is controlled by 2049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FullCodeGenerator::ShouldInlineSmiCase(). 2050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (op) { 2051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::SAR: 2052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ubfx(right, right, kSmiShift, 5); 2053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Asr(result, left, right); 2054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bic(result, result, kSmiShiftMask); 2055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::SHL: 2057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ubfx(right, right, kSmiShift, 5); 2058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Lsl(result, left, right); 2059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::SHR: 2061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If `left >>> right` >= 0x80000000, the result is not representable in a 2062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // signed 32-bit smi. 2063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ubfx(right, right, kSmiShift, 5); 2064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Lsr(x10, left, right); 2065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Tbnz(x10, kXSignBit, &stub_call); 2066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bic(result, x10, kSmiShiftMask); 2067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::ADD: 2069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Adds(x10, left, right); 2070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(vs, &stub_call); 2071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(result, x10); 2072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::SUB: 2074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Subs(x10, left, right); 2075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(vs, &stub_call); 2076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(result, x10); 2077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::MUL: { 2079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label not_minus_zero, done; 2080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(static_cast<unsigned>(kSmiShift) == (kXRegSizeInBits / 2)); 2081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 2082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Smulh(x10, left, right); 2083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cbnz(x10, ¬_minus_zero); 2084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Eor(x11, left, right); 2085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Tbnz(x11, kXSignBit, &stub_call); 2086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(result, x10); 2087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 2088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(¬_minus_zero); 2089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cls(x11, x10); 2090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(x11, kXRegSizeInBits - kSmiShift); 2091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(lt, &stub_call); 2092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(result, x10); 2093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 2094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::BIT_OR: 2097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Orr(result, left, right); 2098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::BIT_AND: 2100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ And(result, left, right); 2101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::BIT_XOR: 2103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Eor(result, left, right); 2104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 2106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 2107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 2110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 2111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, 2115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Token::Value op, 2116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OverwriteMode mode) { 2117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(x1); 2118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op, mode).code(); 2119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JumpPatchSite patch_site(masm_); // Unbound, signals no inlined smi code. 2120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 2121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::BlockPoolsScope scope(masm_); 2122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(code, expr->BinaryOperationFeedbackId()); 2123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patch_site.EmitPatchInfo(); 2124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 2126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitAssignment(Expression* expr) { 2130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->IsValidReferenceExpression()); 2131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Left-hand side can only be a property, a global or a (parameter or local) 2133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // slot. 2134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 2135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LhsKind assign_type = VARIABLE; 2136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Property* prop = expr->AsProperty(); 2137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (prop != NULL) { 2138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assign_type = (prop->key()->IsPropertyName()) 2139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? NAMED_PROPERTY 2140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : KEYED_PROPERTY; 2141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (assign_type) { 2144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case VARIABLE: { 2145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* var = expr->AsVariableProxy()->var(); 2146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EffectContext context(this); 2147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitVariableAssignment(var, Token::ASSIGN); 2148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case NAMED_PROPERTY: { 2151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); // Preserve value. 2152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(prop->obj()); 2153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(all): We could introduce a VisitForRegValue(reg, expr) to avoid 2154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // this copy. 2155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(StoreDescriptor::ReceiverRegister(), x0); 2156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(StoreDescriptor::ValueRegister()); // Restore value. 2157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(StoreDescriptor::NameRegister(), 2158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(prop->key()->AsLiteral()->value())); 2159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallStoreIC(); 2160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case KEYED_PROPERTY: { 2163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); // Preserve value. 2164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(prop->obj()); 2165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(prop->key()); 2166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(StoreDescriptor::NameRegister(), x0); 2167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(StoreDescriptor::ReceiverRegister(), 2168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StoreDescriptor::ValueRegister()); 2169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = 2170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code(); 2171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic); 2172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 2176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( 2180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* var, MemOperand location) { 2181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(result_register(), location); 2182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->IsContextSlot()) { 2183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // RecordWrite may destroy all its register arguments. 2184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x10, result_register()); 2185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = Context::SlotOffset(var->index()); 2186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteContextSlot( 2187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x1, offset, x10, x11, kLRHasBeenSaved, kDontSaveFPRegs); 2188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitVariableAssignment(Variable* var, 2193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Token::Value op) { 2194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitVariableAssignment"); 2195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->IsUnallocated()) { 2196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Global var, const, or let. 2197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(StoreDescriptor::NameRegister(), Operand(var->name())); 2198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(StoreDescriptor::ReceiverRegister(), GlobalObjectMemOperand()); 2199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallStoreIC(); 2200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (op == Token::INIT_CONST_LEGACY) { 2202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Const initializers need a write barrier. 2203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!var->IsParameter()); // No const parameters. 2204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->IsLookupSlot()) { 2205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x1, Operand(var->name())); 2206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0, cp, x1); 2207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); 2208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsStackLocal() || var->IsContextSlot()); 2210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label skip; 2211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand location = VarOperand(var, x1); 2212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x10, location); 2213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotRoot(x10, Heap::kTheHoleValueRootIndex, &skip); 2214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitStoreToStackLocalOrContextSlot(var, location); 2215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&skip); 2216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (var->mode() == LET && op != Token::INIT_LET) { 2219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Non-initializing assignment to let variable needs a write barrier. 2220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!var->IsLookupSlot()); 2221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 2222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label assign; 2223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand location = VarOperand(var, x1); 2224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x10, location); 2225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotRoot(x10, Heap::kTheHoleValueRootIndex, &assign); 2226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x10, Operand(var->name())); 2227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x10); 2228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kThrowReferenceError, 1); 2229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform the assignment. 2230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&assign); 2231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitStoreToStackLocalOrContextSlot(var, location); 2232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (!var->is_const_mode() || op == Token::INIT_CONST) { 2234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->IsLookupSlot()) { 2235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Assignment to var. 2236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x11, Operand(var->name())); 2237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x10, Smi::FromInt(strict_mode())); 2238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // jssp[0] : mode. 2239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // jssp[8] : name. 2240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // jssp[16] : context. 2241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // jssp[24] : value. 2242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0, cp, x11, x10); 2243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kStoreLookupSlot, 4); 2244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Assignment to var or initializing assignment to let/const in harmony 2246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // mode. 2247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 2248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand location = VarOperand(var, x1); 2249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code && op == Token::INIT_LET) { 2250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x10, location); 2251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(x10, Heap::kTheHoleValueRootIndex); 2252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(eq, kLetBindingReInitialization); 2253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitStoreToStackLocalOrContextSlot(var, location); 2255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Non-initializing assignments to consts are ignored. 2258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 2262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitNamedPropertyAssignment"); 2263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Assignment to a property, using a named store IC. 2264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Property* prop = expr->target()->AsProperty(); 2265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(prop != NULL); 2266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(prop->key()->IsLiteral()); 2267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record source code position before IC call. 2269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetSourcePosition(expr->position()); 2270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(StoreDescriptor::NameRegister(), 2271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(prop->key()->AsLiteral()->value())); 2272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(StoreDescriptor::ReceiverRegister()); 2273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallStoreIC(expr->AssignmentFeedbackId()); 2274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 2276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 2277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 2281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitKeyedPropertyAssignment"); 2282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Assignment to a property, using a keyed store IC. 2283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record source code position before IC call. 2285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetSourcePosition(expr->position()); 2286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(all): Could we pass this in registers rather than on the stack? 2287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(StoreDescriptor::NameRegister(), StoreDescriptor::ReceiverRegister()); 2288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(StoreDescriptor::ValueRegister().is(x0)); 2289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code(); 2291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, expr->AssignmentFeedbackId()); 2292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 2294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 2295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitProperty(Property* expr) { 2299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Property"); 2300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* key = expr->key(); 2301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (key->IsPropertyName()) { 2303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!expr->IsSuperAccess()) { 2304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(expr->obj()); 2305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(LoadDescriptor::ReceiverRegister(), x0); 2306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitNamedPropertyLoad(expr); 2307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitNamedSuperPropertyLoad(expr); 2309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(expr->LoadId(), TOS_REG); 2311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 2312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(expr->obj()); 2314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(expr->key()); 2315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(LoadDescriptor::NameRegister(), x0); 2316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(LoadDescriptor::ReceiverRegister()); 2317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitKeyedPropertyLoad(expr); 2318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 2319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::CallIC(Handle<Code> code, 2324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TypeFeedbackId ast_id) { 2325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ic_total_count_++; 2326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // All calls must have a predictable size in full-codegen code to ensure that 2327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the debugger can patch them correctly. 2328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Call(code, RelocInfo::CODE_TARGET, ast_id); 2329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Code common for calls using the IC. 2333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCallWithLoadIC(Call* expr) { 2334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* callee = expr->expression(); 2335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallICState::CallType call_type = 2337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch callee->IsVariableProxy() ? CallICState::FUNCTION : CallICState::METHOD; 2338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the target function. 2340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (call_type == CallICState::FUNCTION) { 2341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { StackValueContext context(this); 2342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitVariableLoad(callee->AsVariableProxy()); 2343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailout(callee, NO_REGISTERS); 2344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push undefined as receiver. This is patched in the method prologue if it 2346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is a sloppy mode method. 2347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(isolate()->factory()->undefined_value()); 2348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the function from the receiver. 2350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(callee->IsProperty()); 2351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!callee->AsProperty()->IsSuperAccess()); 2352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(LoadDescriptor::ReceiverRegister(), 0); 2353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitNamedPropertyLoad(callee->AsProperty()); 2354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); 2355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the target function under the receiver. 2356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(x10); 2357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0, x10); 2358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCall(expr, call_type); 2361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) { 2365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* callee = expr->expression(); 2366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(callee->IsProperty()); 2367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Property* prop = callee->AsProperty(); 2368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(prop->IsSuperAccess()); 2369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetSourcePosition(prop->position()); 2371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Literal* key = prop->key()->AsLiteral(); 2372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!key->value()->IsSmi()); 2373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the function from the receiver. 2375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register scratch = x10; 2376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SuperReference* super_ref = callee->AsProperty()->obj()->AsSuperReference(); 2377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitLoadHomeObject(super_ref); 2378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); 2379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(super_ref->this_var()); 2380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); 2381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(scratch, kPointerSize); 2382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(scratch, x0); 2383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(key->value()); 2384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Stack here: 2386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - home_object 2387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - this (receiver) 2388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - home_object <-- LoadFromSuper will pop here and below. 2389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - this (receiver) 2390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - key 2391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kLoadFromSuper, 3); 2392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Replace home_object with target function. 2394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Poke(x0, kPointerSize); 2395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Stack here: 2397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - target function 2398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - this (receiver) 2399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCall(expr, CallICState::METHOD); 2400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Code common for calls using the IC. 2404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, 2405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* key) { 2406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the key. 2407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(key); 2408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* callee = expr->expression(); 2410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the function from the receiver. 2412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(callee->IsProperty()); 2413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(LoadDescriptor::ReceiverRegister(), 0); 2414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(LoadDescriptor::NameRegister(), x0); 2415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitKeyedPropertyLoad(callee->AsProperty()); 2416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); 2417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the target function under the receiver. 2419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(x10); 2420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0, x10); 2421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCall(expr, CallICState::METHOD); 2423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) { 2427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the arguments. 2428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int arg_count = args->length(); 2430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { PreservePositionScope scope(masm()->positions_recorder()); 2431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < arg_count; i++) { 2432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(i)); 2433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record source position of the IC call. 2436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetSourcePosition(expr->position()); 2437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = CallIC::initialize_stub( 2439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate(), arg_count, call_type); 2440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x3, Smi::FromInt(expr->CallFeedbackSlot())); 2441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(x1, (arg_count + 1) * kXRegSize); 2442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Don't assign a type feedback id to the IC, since type feedback is provided 2443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // by the vector above. 2444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic); 2445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordJSReturnSite(expr); 2447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore context register. 2448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->DropAndPlug(1, x0); 2450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { 2454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitResolvePossiblyDirectEval"); 2455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Prepare to push a copy of the first argument or undefined if it doesn't 2456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // exist. 2457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (arg_count > 0) { 2458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(x9, arg_count * kXRegSize); 2459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x9, Heap::kUndefinedValueRootIndex); 2461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x10, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 2464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Prepare to push the receiver of the enclosing function. 2465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int receiver_offset = 2 + info_->scope()->num_parameters(); 2466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x11, MemOperand(fp, receiver_offset * kPointerSize)); 2467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Prepare to push the language mode. 2469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x12, Smi::FromInt(strict_mode())); 2470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Prepare to push the start position of the scope the calls resides in. 2471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x13, Smi::FromInt(scope()->start_position())); 2472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push. 2474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x9, x10, x11, x12, x13); 2475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do the runtime call. 2477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 6); 2478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitCall(Call* expr) { 2482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG 2483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We want to verify that RecordJSReturnSite gets called on all paths 2484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // through this function. Avoid early returns. 2485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch expr->return_is_recorded_ = false; 2486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 2487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Call"); 2489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* callee = expr->expression(); 2490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Call::CallType call_type = expr->GetCallType(isolate()); 2491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (call_type == Call::POSSIBLY_EVAL_CALL) { 2493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval 2494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to resolve the function we need to call and the receiver of the 2495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // call. Then we call the resolved function using the given 2496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // arguments. 2497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int arg_count = args->length(); 2499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 2501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PreservePositionScope pos_scope(masm()->positions_recorder()); 2502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(callee); 2503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x10, Heap::kUndefinedValueRootIndex); 2504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x10); // Reserved receiver slot. 2505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the arguments. 2507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < arg_count; i++) { 2508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(i)); 2509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push a copy of the function (found below the arguments) and 2512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // resolve eval. 2513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(x10, (arg_count + 1) * kPointerSize); 2514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x10); 2515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitResolvePossiblyDirectEval(arg_count); 2516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The runtime call returns a pair of values in x0 (function) and 2518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // x1 (receiver). Touch up the stack with the right values. 2519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PokePair(x1, x0, arg_count * kPointerSize); 2520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record source position for debugger. 2523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetSourcePosition(expr->position()); 2524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the evaluated function. 2526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS); 2527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(x1, (arg_count + 1) * kXRegSize); 2528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallStub(&stub); 2529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordJSReturnSite(expr); 2530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore context register. 2531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->DropAndPlug(1, x0); 2533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (call_type == Call::GLOBAL_CALL) { 2535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCallWithLoadIC(expr); 2536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (call_type == Call::LOOKUP_SLOT_CALL) { 2538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call to a lookup slot (dynamically introduced variable). 2539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableProxy* proxy = callee->AsVariableProxy(); 2540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow, done; 2541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { PreservePositionScope scope(masm()->positions_recorder()); 2543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generate code for loading from variables potentially shadowed 2544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // by eval-introduced variables. 2545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done); 2546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&slow); 2549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the runtime to find the function to call (returned in x0) 2550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // and the object holding it (returned in x1). 2551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x10, Operand(proxy->name())); 2552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(context_register(), x10); 2553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kLoadLookupSlot, 2); 2554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0, x1); // Receiver, function. 2555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If fast case code has been generated, emit code to push the 2557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // function and receiver and have the slow path jump around this 2558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // code. 2559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (done.is_linked()) { 2560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label call; 2561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&call); 2562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 2563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push function. 2564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The receiver is implicitly the global receiver. Indicate this 2565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // by passing the undefined to the call function stub. 2566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x1, Heap::kUndefinedValueRootIndex); 2567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0, x1); 2568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&call); 2569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The receiver is either the global receiver or an object found 2572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // by LoadContextSlot. 2573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCall(expr); 2574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (call_type == Call::PROPERTY_CALL) { 2575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Property* property = callee->AsProperty(); 2576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_named_call = property->key()->IsPropertyName(); 2577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // super.x() is handled in EmitCallWithLoadIC. 2578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (property->IsSuperAccess() && is_named_call) { 2579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitSuperCallWithLoadIC(expr); 2580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 2582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PreservePositionScope scope(masm()->positions_recorder()); 2583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(property->obj()); 2584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (is_named_call) { 2586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCallWithLoadIC(expr); 2587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitKeyedCallWithLoadIC(expr, property->key()); 2589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(call_type == Call::OTHER_CALL); 2593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call to an arbitrary expression not handled specially above. 2594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { PreservePositionScope scope(masm()->positions_recorder()); 2595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(callee); 2596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x1, Heap::kUndefinedValueRootIndex); 2598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x1); 2599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit function call. 2600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCall(expr); 2601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG 2604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // RecordJSReturnSite should have been called. 2605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->return_is_recorded_); 2606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 2607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitCallNew(CallNew* expr) { 2611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ CallNew"); 2612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // According to ECMA-262, section 11.2.2, page 44, the function 2613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // expression in new calls must be evaluated before the 2614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // arguments. 2615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push constructor on the stack. If it's not a function it's used as 2617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is 2618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ignored. 2619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(expr->expression()); 2620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the arguments ("left-to-right") on the stack. 2622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int arg_count = args->length(); 2624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < arg_count; i++) { 2625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(i)); 2626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the construct call builtin that handles allocation and 2629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // constructor invocation. 2630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetSourcePosition(expr->position()); 2631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load function and argument count into x1 and x0. 2633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x0, arg_count); 2634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(x1, arg_count * kXRegSize); 2635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record call targets in unoptimized code. 2637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_pretenuring_call_new) { 2638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot()); 2639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->AllocationSiteFeedbackSlot() == 2640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch expr->CallNewFeedbackSlot() + 1); 2641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadObject(x2, FeedbackVector()); 2644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x3, Smi::FromInt(expr->CallNewFeedbackSlot())); 2645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET); 2647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); 2648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(expr->ReturnId(), TOS_REG); 2649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 2650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { 2654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 2656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); 2658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false; 2660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true = NULL; 2661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false = NULL; 2662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through = NULL; 2663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 2664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &if_true, &if_false, &fall_through); 2665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TestAndSplit(x0, kSmiTagMask, if_true, if_false, fall_through); 2668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(if_true, if_false); 2670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) { 2674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 2676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); 2678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false; 2680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true = NULL; 2681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false = NULL; 2682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through = NULL; 2683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 2684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &if_true, &if_false, &fall_through); 2685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t sign_mask = V8_UINT64_C(1) << (kSmiShift + kSmiValueSize - 1); 2687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TestAndSplit(x0, kSmiTagMask | sign_mask, if_true, if_false, fall_through); 2690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(if_true, if_false); 2692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitIsObject(CallRuntime* expr) { 2696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 2698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); 2700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false; 2702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true = NULL; 2703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false = NULL; 2704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through = NULL; 2705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 2706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &if_true, &if_false, &fall_through); 2707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x0, if_false); 2709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfRoot(x0, Heap::kNullValueRootIndex, if_true); 2710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x10, FieldMemOperand(x0, HeapObject::kMapOffset)); 2711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Undetectable objects behave like undefined when tested with typeof. 2712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrb(x11, FieldMemOperand(x10, Map::kBitFieldOffset)); 2713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Tbnz(x11, Map::kIsUndetectable, if_false); 2714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrb(x12, FieldMemOperand(x10, Map::kInstanceTypeOffset)); 2715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(x12, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); 2716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(lt, if_false); 2717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(x12, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); 2718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(le, if_true, if_false, fall_through); 2720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(if_true, if_false); 2722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) { 2726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 2728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); 2730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false; 2732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true = NULL; 2733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false = NULL; 2734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through = NULL; 2735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 2736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &if_true, &if_false, &fall_through); 2737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x0, if_false); 2739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareObjectType(x0, x10, x11, FIRST_SPEC_OBJECT_TYPE); 2740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(ge, if_true, if_false, fall_through); 2742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(if_true, if_false); 2744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) { 2748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitIsUndetectableObject"); 2749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 2751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); 2753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false; 2755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true = NULL; 2756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false = NULL; 2757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through = NULL; 2758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 2759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &if_true, &if_false, &fall_through); 2760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x0, if_false); 2762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x10, FieldMemOperand(x0, HeapObject::kMapOffset)); 2763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrb(x11, FieldMemOperand(x10, Map::kBitFieldOffset)); 2764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Tst(x11, 1 << Map::kIsUndetectable); 2765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(ne, if_true, if_false, fall_through); 2767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(if_true, if_false); 2769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( 2773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallRuntime* expr) { 2774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 2776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); 2777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false, skip_lookup; 2779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true = NULL; 2780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false = NULL; 2781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through = NULL; 2782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 2783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &if_true, &if_false, &fall_through); 2784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object = x0; 2786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AssertNotSmi(object); 2787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register map = x10; 2789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register bitfield2 = x11; 2790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(map, FieldMemOperand(object, HeapObject::kMapOffset)); 2791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrb(bitfield2, FieldMemOperand(map, Map::kBitField2Offset)); 2792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Tbnz(bitfield2, Map::kStringWrapperSafeForDefaultValueOf, &skip_lookup); 2793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for fast case object. Generate false result for slow case object. 2795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register props = x12; 2796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register props_map = x12; 2797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register hash_table_map = x13; 2798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(props, FieldMemOperand(object, JSObject::kPropertiesOffset)); 2799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(props_map, FieldMemOperand(props, HeapObject::kMapOffset)); 2800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(hash_table_map, Heap::kHashTableMapRootIndex); 2801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(props_map, hash_table_map); 2802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(eq, if_false); 2803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Look for valueOf name in the descriptor array, and indicate false if found. 2805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Since we omit an enumeration index check, if it is added via a transition 2806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // that shares its descriptor array, this is a false positive. 2807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label loop, done; 2808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Skip loop if no descriptors are valid. 2810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register descriptors = x12; 2811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register descriptors_length = x13; 2812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ NumberOfOwnDescriptors(descriptors_length, map); 2813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cbz(descriptors_length, &done); 2814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadInstanceDescriptors(map, descriptors); 2816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Calculate the end of the descriptor array. 2818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register descriptors_end = x14; 2819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x15, DescriptorArray::kDescriptorSize); 2820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mul(descriptors_length, descriptors_length, x15); 2821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Calculate location of the first key name. 2822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Add(descriptors, descriptors, 2823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DescriptorArray::kFirstOffset - kHeapObjectTag); 2824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Calculate the end of the descriptor array. 2825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Add(descriptors_end, descriptors, 2826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(descriptors_length, LSL, kPointerSizeLog2)); 2827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Loop through all the keys in the descriptor array. If one of these is the 2829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // string "valueOf" the result is false. 2830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register valueof_string = x1; 2831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int descriptor_size = DescriptorArray::kDescriptorSize * kPointerSize; 2832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(valueof_string, Operand(isolate()->factory()->value_of_string())); 2833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&loop); 2834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x15, MemOperand(descriptors, descriptor_size, PostIndex)); 2835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(x15, valueof_string); 2836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(eq, if_false); 2837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(descriptors, descriptors_end); 2838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(ne, &loop); 2839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 2841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Set the bit in the map to indicate that there is no local valueOf field. 2843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrb(x2, FieldMemOperand(map, Map::kBitField2Offset)); 2844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Orr(x2, x2, 1 << Map::kStringWrapperSafeForDefaultValueOf); 2845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Strb(x2, FieldMemOperand(map, Map::kBitField2Offset)); 2846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&skip_lookup); 2848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If a valueOf property is not found on the object check that its prototype 2850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is the unmodified String prototype. If not result is false. 2851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register prototype = x1; 2852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register global_idx = x2; 2853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register native_context = x2; 2854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register string_proto = x3; 2855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register proto_map = x4; 2856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(prototype, FieldMemOperand(map, Map::kPrototypeOffset)); 2857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(prototype, if_false); 2858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(proto_map, FieldMemOperand(prototype, HeapObject::kMapOffset)); 2859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(global_idx, GlobalObjectMemOperand()); 2860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(native_context, 2861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldMemOperand(global_idx, GlobalObject::kNativeContextOffset)); 2862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(string_proto, 2863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ContextMemOperand(native_context, 2864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); 2865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(proto_map, string_proto); 2866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(eq, if_true, if_false, fall_through); 2869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(if_true, if_false); 2871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitIsFunction(CallRuntime* expr) { 2875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 2877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); 2879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false; 2881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true = NULL; 2882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false = NULL; 2883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through = NULL; 2884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 2885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &if_true, &if_false, &fall_through); 2886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x0, if_false); 2888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareObjectType(x0, x10, x11, JS_FUNCTION_TYPE); 2889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(eq, if_true, if_false, fall_through); 2891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(if_true, if_false); 2893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) { 2897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 2899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); 2901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false; 2903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true = NULL; 2904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false = NULL; 2905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through = NULL; 2906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 2907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &if_true, &if_false, &fall_through); 2908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Only a HeapNumber can be -0.0, so return false if we have something else. 2910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotHeapNumber(x0, if_false, DO_SMI_CHECK); 2911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Test the bit pattern. 2913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x10, FieldMemOperand(x0, HeapNumber::kValueOffset)); 2914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(x10, 1); // Set V on 0x8000000000000000. 2915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(vs, if_true, if_false, fall_through); 2918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(if_true, if_false); 2920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitIsArray(CallRuntime* expr) { 2924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 2926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); 2928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false; 2930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true = NULL; 2931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false = NULL; 2932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through = NULL; 2933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 2934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &if_true, &if_false, &fall_through); 2935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x0, if_false); 2937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareObjectType(x0, x10, x11, JS_ARRAY_TYPE); 2938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(eq, if_true, if_false, fall_through); 2940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(if_true, if_false); 2942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) { 2946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 2948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); 2950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false; 2952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true = NULL; 2953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false = NULL; 2954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through = NULL; 2955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 2956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &if_true, &if_false, &fall_through); 2957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x0, if_false); 2959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareObjectType(x0, x10, x11, JS_REGEXP_TYPE); 2960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(eq, if_true, if_false, fall_through); 2962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(if_true, if_false); 2964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) { 2969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->arguments()->length() == 0); 2970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false; 2972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true = NULL; 2973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false = NULL; 2974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through = NULL; 2975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 2976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &if_true, &if_false, &fall_through); 2977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the frame pointer for the calling frame. 2979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 2980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Skip the arguments adaptor frame if it exists. 2982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label check_frame_marker; 2983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x1, MemOperand(x2, StandardFrameConstants::kContextOffset)); 2984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(x1, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(ne, &check_frame_marker); 2986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x2, MemOperand(x2, StandardFrameConstants::kCallerFPOffset)); 2987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check the marker in the calling frame. 2989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&check_frame_marker); 2990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x1, MemOperand(x2, StandardFrameConstants::kMarkerOffset)); 2991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(x1, Smi::FromInt(StackFrame::CONSTRUCT)); 2992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(eq, if_true, if_false, fall_through); 2994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(if_true, if_false); 2996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) { 3000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 2); 3002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the two objects into registers and perform the comparison. 3004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(0)); 3005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(1)); 3006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false; 3008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true = NULL; 3009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false = NULL; 3010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through = NULL; 3011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 3012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &if_true, &if_false, &fall_through); 3013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(x1); 3015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(x0, x1); 3016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(eq, if_true, if_false, fall_through); 3018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(if_true, if_false); 3020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitArguments(CallRuntime* expr) { 3024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 3026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ArgumentsAccessStub expects the key in x1. 3028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); 3029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x1, x0); 3030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x0, Smi::FromInt(info_->scope()->num_parameters())); 3031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArgumentsAccessStub stub(isolate(), ArgumentsAccessStub::READ_ELEMENT); 3032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallStub(&stub); 3033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 3034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { 3038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->arguments()->length() == 0); 3039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label exit; 3040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the number of formal parameters. 3041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x0, Smi::FromInt(info_->scope()->num_parameters())); 3042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if the calling frame is an arguments adaptor frame. 3044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x12, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 3045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x13, MemOperand(x12, StandardFrameConstants::kContextOffset)); 3046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(x13, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 3047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(ne, &exit); 3048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Arguments adaptor case: Read the arguments length from the 3050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // adaptor frame. 3051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x0, MemOperand(x12, ArgumentsAdaptorFrameConstants::kLengthOffset)); 3052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&exit); 3054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 3055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitClassOf(CallRuntime* expr) { 3059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitClassOf"); 3060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 3062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done, null, function, non_function_constructor; 3063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); 3065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the object is a smi, we return null. 3067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x0, &null); 3068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the object is a JS object but take special care of JS 3070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // functions to make sure they have 'Function' as their class. 3071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Assume that there are only two callable types, and one of them is at 3072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // either end of the type range for JS object types. Saves extra comparisons. 3073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); 3074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareObjectType(x0, x10, x11, FIRST_SPEC_OBJECT_TYPE); 3075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // x10: object's map. 3076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // x11: object's type. 3077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(lt, &null); 3078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == 3079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FIRST_SPEC_OBJECT_TYPE + 1); 3080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(eq, &function); 3081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(x11, LAST_SPEC_OBJECT_TYPE); 3083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == 3084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LAST_SPEC_OBJECT_TYPE - 1); 3085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(eq, &function); 3086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Assume that there is no larger type. 3087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1); 3088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if the constructor in the map is a JS function. 3090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x12, FieldMemOperand(x10, Map::kConstructorOffset)); 3091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotObjectType(x12, x13, x14, JS_FUNCTION_TYPE, 3092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &non_function_constructor); 3093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // x12 now contains the constructor function. Grab the 3095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // instance class name from there. 3096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x13, FieldMemOperand(x12, JSFunction::kSharedFunctionInfoOffset)); 3097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x0, 3098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldMemOperand(x13, SharedFunctionInfo::kInstanceClassNameOffset)); 3099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 3100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Functions have class 'Function'. 3102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&function); 3103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x0, Heap::kFunction_stringRootIndex); 3104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 3105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Objects with a non-function constructor have class 'Object'. 3107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&non_function_constructor); 3108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x0, Heap::kObject_stringRootIndex); 3109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 3110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Non-JS objects have class null. 3112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&null); 3113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x0, Heap::kNullValueRootIndex); 3114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // All done. 3116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 3117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 3119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitSubString(CallRuntime* expr) { 3123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the arguments on the stack and call the stub. 3124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SubStringStub stub(isolate()); 3125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 3); 3127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(0)); 3128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(1)); 3129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(2)); 3130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallStub(&stub); 3131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 3132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) { 3136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the arguments on the stack and call the stub. 3137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RegExpExecStub stub(isolate()); 3138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 4); 3140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(0)); 3141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(1)); 3142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(2)); 3143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(3)); 3144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallStub(&stub); 3145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 3146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitValueOf(CallRuntime* expr) { 3150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitValueOf"); 3151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 3153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); // Load the object. 3154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 3156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the object is a smi return the object. 3157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x0, &done); 3158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the object is not a value type, return the object. 3159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotObjectType(x0, x10, x11, JS_VALUE_TYPE, &done); 3160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x0, FieldMemOperand(x0, JSValue::kValueOffset)); 3161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 3163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 3164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDateField(CallRuntime* expr) { 3168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 2); 3170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_NE(NULL, args->at(1)->AsLiteral()); 3171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value())); 3172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); // Load the object. 3174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label runtime, done, not_date_object; 3176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object = x0; 3177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = x0; 3178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register stamp_addr = x10; 3179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register stamp_cache = x11; 3180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(object, ¬_date_object); 3182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotObjectType(object, x10, x10, JS_DATE_TYPE, ¬_date_object); 3183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (index->value() == 0) { 3185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(result, FieldMemOperand(object, JSDate::kValueOffset)); 3186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 3187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (index->value() < JSDate::kFirstUncachedField) { 3189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); 3190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x10, stamp); 3191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(stamp_addr, MemOperand(x10)); 3192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(stamp_cache, FieldMemOperand(object, JSDate::kCacheStampOffset)); 3193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(stamp_addr, stamp_cache); 3194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(ne, &runtime); 3195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(result, FieldMemOperand(object, JSDate::kValueOffset + 3196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kPointerSize * index->value())); 3197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 3198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&runtime); 3201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x1, index); 3202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); 3203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 3204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(¬_date_object); 3207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kThrowNotDateError, 0); 3208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 3209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 3210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { 3214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(3, args->length()); 3216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register string = x0; 3218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register index = x1; 3219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value = x2; 3220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch = x10; 3221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(0)); // index 3223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(1)); // value 3224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(2)); // string 3225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(value, index); 3226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code) { 3228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AssertSmi(value, kNonSmiValue); 3229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AssertSmi(index, kNonSmiIndex); 3230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; 3231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ EmitSeqStringSetCharCheck(string, index, kIndexIsSmi, scratch, 3232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch one_byte_seq_type); 3233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Add(scratch, string, SeqOneByteString::kHeaderSize - kHeapObjectTag); 3236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(value); 3237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(index); 3238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Strb(value, MemOperand(scratch, index)); 3239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(string); 3240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { 3244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(3, args->length()); 3246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register string = x0; 3248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register index = x1; 3249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value = x2; 3250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch = x10; 3251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(0)); // index 3253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(1)); // value 3254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(2)); // string 3255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(value, index); 3256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code) { 3258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AssertSmi(value, kNonSmiValue); 3259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AssertSmi(index, kNonSmiIndex); 3260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; 3261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ EmitSeqStringSetCharCheck(string, index, kIndexIsSmi, scratch, 3262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch two_byte_seq_type); 3263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Add(scratch, string, SeqTwoByteString::kHeaderSize - kHeapObjectTag); 3266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(value); 3267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(index); 3268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Strh(value, MemOperand(scratch, index, LSL, 1)); 3269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(string); 3270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitMathPow(CallRuntime* expr) { 3274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the arguments on the stack and call the MathPow stub. 3275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 2); 3277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(0)); 3278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(1)); 3279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MathPowStub stub(isolate(), MathPowStub::ON_STACK); 3280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallStub(&stub); 3281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 3282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { 3286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 2); 3288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(0)); // Load the object. 3289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(1)); // Load the value. 3290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(x1); 3291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // x0 = value. 3292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // x1 = object. 3293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 3295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the object is a smi, return the value. 3296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x1, &done); 3297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the object is not a value type, return the value. 3299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotObjectType(x1, x10, x11, JS_VALUE_TYPE, &done); 3300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store the value. 3302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(x0, FieldMemOperand(x1, JSValue::kValueOffset)); 3303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update the write barrier. Save the value as it will be 3304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // overwritten by the write barrier code and is needed afterward. 3305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x10, x0); 3306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteField( 3307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x1, JSValue::kValueOffset, x10, x11, kLRHasBeenSaved, kDontSaveFPRegs); 3308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 3310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 3311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { 3315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(args->length(), 1); 3317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the argument into x0 and call the stub. 3319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); 3320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NumberToStringStub stub(isolate()); 3322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallStub(&stub); 3323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 3324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { 3328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 3330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); 3332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 3334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register code = x0; 3335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = x1; 3336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StringCharFromCodeGenerator generator(code, result); 3338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch generator.GenerateFast(masm_); 3339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 3340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NopRuntimeCallHelper call_helper; 3342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch generator.GenerateSlow(masm_, call_helper); 3343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 3345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(result); 3346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { 3350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 2); 3352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(0)); 3354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(1)); 3355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object = x1; 3357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register index = x0; 3358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = x3; 3359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(object); 3361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label need_conversion; 3363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label index_out_of_range; 3364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 3365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StringCharCodeAtGenerator generator(object, 3366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch index, 3367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result, 3368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &need_conversion, 3369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &need_conversion, 3370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &index_out_of_range, 3371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STRING_INDEX_IS_NUMBER); 3372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch generator.GenerateFast(masm_); 3373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 3374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&index_out_of_range); 3376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // When the index is out of range, the spec requires us to return NaN. 3377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(result, Heap::kNanValueRootIndex); 3378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 3379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&need_conversion); 3381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the undefined value into the result register, which will 3382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // trigger conversion. 3383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(result, Heap::kUndefinedValueRootIndex); 3384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 3385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NopRuntimeCallHelper call_helper; 3387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch generator.GenerateSlow(masm_, call_helper); 3388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 3390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(result); 3391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) { 3395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 2); 3397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(0)); 3399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(1)); 3400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object = x1; 3402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register index = x0; 3403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = x0; 3404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(object); 3406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label need_conversion; 3408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label index_out_of_range; 3409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 3410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StringCharAtGenerator generator(object, 3411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch index, 3412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x3, 3413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result, 3414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &need_conversion, 3415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &need_conversion, 3416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &index_out_of_range, 3417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STRING_INDEX_IS_NUMBER); 3418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch generator.GenerateFast(masm_); 3419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 3420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&index_out_of_range); 3422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // When the index is out of range, the spec requires us to return 3423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the empty string. 3424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(result, Heap::kempty_stringRootIndex); 3425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 3426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&need_conversion); 3428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Move smi zero into the result register, which will trigger conversion. 3429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(result, Smi::FromInt(0)); 3430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 3431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NopRuntimeCallHelper call_helper; 3433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch generator.GenerateSlow(masm_, call_helper); 3434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 3436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(result); 3437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { 3441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitStringAdd"); 3442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(2, args->length()); 3444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(0)); 3446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(1)); 3447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(x1); 3449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED); 3450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallStub(&stub); 3451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 3453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { 3457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(2, args->length()); 3459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(0)); 3460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(1)); 3461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StringCompareStub stub(isolate()); 3463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallStub(&stub); 3464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 3465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { 3469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitCallFunction"); 3470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() >= 2); 3472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int arg_count = args->length() - 2; // 2 ~ receiver and function. 3474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < arg_count + 1; i++) { 3475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(i)); 3476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->last()); // Function. 3478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label runtime, done; 3480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for non-function argument (including proxy). 3481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x0, &runtime); 3482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotObjectType(x0, x1, x1, JS_FUNCTION_TYPE, &runtime); 3483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // InvokeFunction requires the function in x1. Move it in there. 3485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x1, x0); 3486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ParameterCount count(arg_count); 3487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeFunction(x1, count, CALL_FUNCTION, NullCallWrapper()); 3488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 3489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 3490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&runtime); 3492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); 3493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kCall, args->length()); 3494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 3495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 3497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { 3501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RegExpConstructResultStub stub(isolate()); 3502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 3); 3504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(0)); 3505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(1)); 3506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(2)); 3507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(x1, x2); 3508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallStub(&stub); 3509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 3510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { 3514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(2, args->length()); 3516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_NE(NULL, args->at(0)->AsLiteral()); 3517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->value()))->value(); 3518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<FixedArray> jsfunction_result_caches( 3520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate()->native_context()->jsfunction_result_caches()); 3521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (jsfunction_result_caches->length() <= cache_id) { 3522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Abort(kAttemptToUseUndefinedCache); 3523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); 3524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 3525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 3526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(1)); 3529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register key = x0; 3531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register cache = x1; 3532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(cache, GlobalObjectMemOperand()); 3533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(cache, FieldMemOperand(cache, GlobalObject::kNativeContextOffset)); 3534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(cache, ContextMemOperand(cache, 3535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Context::JSFUNCTION_RESULT_CACHES_INDEX)); 3536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(cache, 3537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldMemOperand(cache, FixedArray::OffsetOfElementAt(cache_id))); 3538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 3540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrsw(x2, UntagSmiFieldMemOperand(cache, 3541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSFunctionResultCache::kFingerOffset)); 3542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Add(x3, cache, FixedArray::kHeaderSize - kHeapObjectTag); 3543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Add(x3, x3, Operand(x2, LSL, kPointerSizeLog2)); 3544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the key and data from the cache. 3546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldp(x2, x3, MemOperand(x3)); 3547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(key, x2); 3549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmovX(x0, x3, eq); 3550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(eq, &done); 3551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call runtime to perform the lookup. 3553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(cache, key); 3554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kGetFromCache, 2); 3555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 3557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 3558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { 3562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); 3564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false; 3566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true = NULL; 3567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false = NULL; 3568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through = NULL; 3569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 3570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &if_true, &if_false, &fall_through); 3571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x10, FieldMemOperand(x0, String::kHashFieldOffset)); 3573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Tst(x10, String::kContainsCachedArrayIndexMask); 3574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(eq, if_true, if_false, fall_through); 3576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(if_true, if_false); 3578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) { 3582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 3584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); 3585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AssertString(x0); 3587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x10, FieldMemOperand(x0, String::kHashFieldOffset)); 3589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IndexFromHash(x10, x0); 3590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 3592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitFastOneByteArrayJoin(CallRuntime* expr) { 3596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitFastOneByteArrayJoin"); 3597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 2); 3600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(1)); 3601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); 3602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register array = x0; 3604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = x0; 3605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register elements = x1; 3606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register element = x2; 3607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register separator = x3; 3608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register array_length = x4; 3609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result_pos = x5; 3610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register map = x6; 3611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register string_length = x10; 3612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register elements_end = x11; 3613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register string = x12; 3614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1 = x13; 3615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2 = x14; 3616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch3 = x7; 3617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register separator_length = x15; 3618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label bailout, done, one_char_separator, long_separator, 3620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch non_trivial_array, not_size_one_array, loop, 3621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch empty_separator_loop, one_char_separator_loop, 3622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch one_char_separator_loop_entry, long_separator_loop; 3623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The separator operand is on the stack. 3625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(separator); 3626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the array is a JSArray. 3628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(array, &bailout); 3629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotObjectType(array, map, scratch1, JS_ARRAY_TYPE, &bailout); 3630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the array has fast elements. 3632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CheckFastElements(map, scratch1, &bailout); 3633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the array has length zero, return the empty string. 3635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load and untag the length of the array. 3636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // It is an unsigned value, so we can skip sign extension. 3637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We assume little endianness. 3638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrsw(array_length, 3639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UntagSmiFieldMemOperand(array, JSArray::kLengthOffset)); 3640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cbnz(array_length, &non_trivial_array); 3641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(result, Heap::kempty_stringRootIndex); 3642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 3643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&non_trivial_array); 3645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the FixedArray containing array's elements. 3646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(elements, FieldMemOperand(array, JSArray::kElementsOffset)); 3647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that all array elements are sequential one-byte strings, and 3649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // accumulate the sum of their lengths. 3650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(string_length, 0); 3651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Add(element, elements, FixedArray::kHeaderSize - kHeapObjectTag); 3652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2)); 3653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Loop condition: while (element < elements_end). 3654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Live values in registers: 3655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // elements: Fixed array of strings. 3656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // array_length: Length of the fixed array of strings (not smi) 3657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // separator: Separator string 3658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // string_length: Accumulated sum of string lengths (not smi). 3659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // element: Current array element. 3660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // elements_end: Array end. 3661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code) { 3662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(array_length, 0); 3663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(gt, kNoEmptyArraysHereInEmitFastOneByteArrayJoin); 3664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&loop); 3666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(string, MemOperand(element, kPointerSize, PostIndex)); 3667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(string, &bailout); 3668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(scratch1, FieldMemOperand(string, HeapObject::kMapOffset)); 3669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); 3670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfInstanceTypeIsNotSequentialOneByte(scratch1, scratch2, &bailout); 3671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrsw(scratch1, 3672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UntagSmiFieldMemOperand(string, SeqOneByteString::kLengthOffset)); 3673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Adds(string_length, string_length, scratch1); 3674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(vs, &bailout); 3675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(element, elements_end); 3676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(lt, &loop); 3677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If array_length is 1, return elements[0], a string. 3679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(array_length, 1); 3680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(ne, ¬_size_one_array); 3681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(result, FieldMemOperand(elements, FixedArray::kHeaderSize)); 3682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 3683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(¬_size_one_array); 3685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Live values in registers: 3687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // separator: Separator string 3688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // array_length: Length of the array (not smi). 3689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // string_length: Sum of string lengths (not smi). 3690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // elements: FixedArray of strings. 3691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the separator is a flat one-byte string. 3693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(separator, &bailout); 3694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(scratch1, FieldMemOperand(separator, HeapObject::kMapOffset)); 3695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); 3696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfInstanceTypeIsNotSequentialOneByte(scratch1, scratch2, &bailout); 3697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Add (separator length times array_length) - separator length to the 3699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // string_length to get the length of the result string. 3700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the separator length as untagged. 3701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We assume little endianness, and that the length is positive. 3702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrsw(separator_length, 3703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UntagSmiFieldMemOperand(separator, 3704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SeqOneByteString::kLengthOffset)); 3705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Sub(string_length, string_length, separator_length); 3706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Umaddl(string_length, array_length.W(), separator_length.W(), 3707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch string_length); 3708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get first element in the array. 3710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Add(element, elements, FixedArray::kHeaderSize - kHeapObjectTag); 3711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Live values in registers: 3712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // element: First array element 3713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // separator: Separator string 3714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // string_length: Length of result string (not smi) 3715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // array_length: Length of the array (not smi). 3716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AllocateOneByteString(result, string_length, scratch1, scratch2, scratch3, 3717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &bailout); 3718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Prepare for looping. Set up elements_end to end of the array. Set 3720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // result_pos to the position of the result where to write the first 3721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // character. 3722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(all): useless unless AllocateOneByteString trashes the register. 3723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2)); 3724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Add(result_pos, result, SeqOneByteString::kHeaderSize - kHeapObjectTag); 3725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check the length of the separator. 3727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(separator_length, 1); 3728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(eq, &one_char_separator); 3729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(gt, &long_separator); 3730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Empty separator case 3732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&empty_separator_loop); 3733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Live values in registers: 3734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // result_pos: the position to which we are currently copying characters. 3735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // element: Current array element. 3736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // elements_end: Array end. 3737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Copy next array element to the result. 3739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(string, MemOperand(element, kPointerSize, PostIndex)); 3740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrsw(string_length, 3741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UntagSmiFieldMemOperand(string, String::kLengthOffset)); 3742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Add(string, string, SeqOneByteString::kHeaderSize - kHeapObjectTag); 3743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CopyBytes(result_pos, string, string_length, scratch1); 3744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(element, elements_end); 3745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(lt, &empty_separator_loop); // End while (element < elements_end). 3746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 3747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // One-character separator case 3749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&one_char_separator); 3750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Replace separator with its one-byte character value. 3751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrb(separator, FieldMemOperand(separator, SeqOneByteString::kHeaderSize)); 3752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Jump into the loop after the code that copies the separator, so the first 3753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // element is not preceded by a separator 3754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&one_char_separator_loop_entry); 3755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&one_char_separator_loop); 3757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Live values in registers: 3758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // result_pos: the position to which we are currently copying characters. 3759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // element: Current array element. 3760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // elements_end: Array end. 3761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // separator: Single separator one-byte char (in lower byte). 3762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Copy the separator character to the result. 3764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Strb(separator, MemOperand(result_pos, 1, PostIndex)); 3765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Copy next array element to the result. 3767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&one_char_separator_loop_entry); 3768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(string, MemOperand(element, kPointerSize, PostIndex)); 3769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrsw(string_length, 3770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UntagSmiFieldMemOperand(string, String::kLengthOffset)); 3771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Add(string, string, SeqOneByteString::kHeaderSize - kHeapObjectTag); 3772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CopyBytes(result_pos, string, string_length, scratch1); 3773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(element, elements_end); 3774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(lt, &one_char_separator_loop); // End while (element < elements_end). 3775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 3776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Long separator case (separator is more than one character). Entry is at the 3778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // label long_separator below. 3779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&long_separator_loop); 3780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Live values in registers: 3781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // result_pos: the position to which we are currently copying characters. 3782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // element: Current array element. 3783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // elements_end: Array end. 3784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // separator: Separator string. 3785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Copy the separator to the result. 3787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(all): hoist next two instructions. 3788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrsw(string_length, 3789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UntagSmiFieldMemOperand(separator, String::kLengthOffset)); 3790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Add(string, separator, SeqOneByteString::kHeaderSize - kHeapObjectTag); 3791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CopyBytes(result_pos, string, string_length, scratch1); 3792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&long_separator); 3794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(string, MemOperand(element, kPointerSize, PostIndex)); 3795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrsw(string_length, 3796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UntagSmiFieldMemOperand(string, String::kLengthOffset)); 3797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Add(string, string, SeqOneByteString::kHeaderSize - kHeapObjectTag); 3798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CopyBytes(result_pos, string, string_length, scratch1); 3799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(element, elements_end); 3800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(lt, &long_separator_loop); // End while (element < elements_end). 3801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 3802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&bailout); 3804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Returning undefined will force slower code to handle it. 3805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(result, Heap::kUndefinedValueRootIndex); 3806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 3807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(result); 3808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { 3812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->arguments()->length() == 0); 3813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference debug_is_active = 3814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::debug_is_active_address(isolate()); 3815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x10, debug_is_active); 3816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrb(x0, MemOperand(x10)); 3817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(x0); 3818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 3819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 3823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->function() != NULL && 3824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch expr->function()->intrinsic_type == Runtime::INLINE) { 3825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ InlineRuntimeCall"); 3826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitInlineRuntimeCall(expr); 3827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 3828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ CallRunTime"); 3831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int arg_count = args->length(); 3833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->is_jsruntime()) { 3835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the builtins object as the receiver. 3836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x10, GlobalObjectMemOperand()); 3837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(LoadDescriptor::ReceiverRegister(), 3838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldMemOperand(x10, GlobalObject::kBuiltinsOffset)); 3839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(LoadDescriptor::ReceiverRegister()); 3840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the function from the receiver. 3842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<String> name = expr->name(); 3843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(LoadDescriptor::NameRegister(), Operand(name)); 3844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 3845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(VectorLoadICDescriptor::SlotRegister(), 3846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(expr->CallRuntimeFeedbackSlot())); 3847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(NOT_CONTEXTUAL); 3848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); 3850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the target function under the receiver. 3853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(x10); 3854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0, x10); 3855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int arg_count = args->length(); 3857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < arg_count; i++) { 3858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(i)); 3859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record source position of the IC call. 3862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetSourcePosition(expr->position()); 3863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS); 3864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(x1, (arg_count + 1) * kPointerSize); 3865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallStub(&stub); 3866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore context register. 3868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 3869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->DropAndPlug(1, x0); 3871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the arguments ("left-to-right"). 3873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < arg_count; i++) { 3874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(i)); 3875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the C runtime function. 3878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(expr->function(), arg_count); 3879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 3880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 3885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (expr->op()) { 3886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::DELETE: { 3887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); 3888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Property* property = expr->expression()->AsProperty(); 3889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableProxy* proxy = expr->expression()->AsVariableProxy(); 3890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (property != NULL) { 3892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(property->obj()); 3893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(property->key()); 3894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x10, Smi::FromInt(strict_mode())); 3895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x10); 3896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 3897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 3898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (proxy != NULL) { 3899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* var = proxy->var(); 3900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Delete of an unqualified identifier is disallowed in strict mode 3901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // but "delete this" is allowed. 3902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(strict_mode() == SLOPPY || var->is_this()); 3903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->IsUnallocated()) { 3904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x12, GlobalObjectMemOperand()); 3905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x11, Operand(var->name())); 3906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x10, Smi::FromInt(SLOPPY)); 3907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x12, x11, x10); 3908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 3909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 3910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (var->IsStackAllocated() || var->IsContextSlot()) { 3911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Result of deleting non-global, non-dynamic variables is false. 3912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The subexpression does not have side effects. 3913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(var->is_this()); 3914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Non-global variable. Call the runtime to try to delete from the 3916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // context where the variable was introduced. 3917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x2, Operand(var->name())); 3918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(context_register(), x2); 3919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kDeleteLookupSlot, 2); 3920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 3921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Result of deleting non-property, non-variable reference is true. 3924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The subexpression may have side effects. 3925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForEffect(expr->expression()); 3926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(true); 3927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 3929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 3930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::VOID: { 3932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ UnaryOperation (VOID)"); 3933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForEffect(expr->expression()); 3934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(Heap::kUndefinedValueRootIndex); 3935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 3936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::NOT: { 3938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 3939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (context()->IsEffect()) { 3940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unary NOT has no side effects so it's only necessary to visit the 3941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // subexpression. Match the optimizing compiler by not branching. 3942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForEffect(expr->expression()); 3943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (context()->IsTest()) { 3944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const TestContext* test = TestContext::cast(context()); 3945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The labels are swapped for the recursive call. 3946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForControl(expr->expression(), 3947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch test->false_label(), 3948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch test->true_label(), 3949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch test->fall_through()); 3950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(test->true_label(), test->false_label()); 3951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue()); 3953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(jbramley): This could be much more efficient using (for 3954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // example) the CSEL instruction. 3955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false, done; 3956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForControl(expr->expression(), 3957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &materialize_false, 3958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &materialize_true, 3959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &materialize_true); 3960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&materialize_true); 3962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS); 3963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(result_register(), Heap::kTrueValueRootIndex); 3964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 3965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&materialize_false); 3967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS); 3968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(result_register(), Heap::kFalseValueRootIndex); 3969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 3970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 3972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (context()->IsStackValue()) { 3973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(result_register()); 3974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 3977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::TYPEOF: { 3979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 3980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 3981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StackValueContext context(this); 3982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForTypeofValue(expr->expression()); 3983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kTypeof, 1); 3985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 3986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 3987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 3989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 3990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 3995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->expression()->IsValidReferenceExpression()); 3996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ CountOperation"); 3998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetSourcePosition(expr->position()); 3999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Expression can only be a property, a global or a (parameter or local) 4001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // slot. 4002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 4003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LhsKind assign_type = VARIABLE; 4004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Property* prop = expr->expression()->AsProperty(); 4005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // In case of a property we use the uninitialized expression context 4006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of the key to detect a named property. 4007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (prop != NULL) { 4008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assign_type = 4009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 4010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Evaluate expression and get value. 4013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (assign_type == VARIABLE) { 4014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->expression()->AsVariableProxy()->var() != NULL); 4015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AccumulatorValueContext context(this); 4016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitVariableLoad(expr->expression()->AsVariableProxy()); 4017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Reserve space for result of postfix operation. 4019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->is_postfix() && !context()->IsEffect()) { 4020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(xzr); 4021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (assign_type == NAMED_PROPERTY) { 4023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Put the object both on the stack and in the register. 4024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(prop->obj()); 4025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(LoadDescriptor::ReceiverRegister(), 0); 4026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitNamedPropertyLoad(prop); 4027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // KEYED_PROPERTY 4029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(prop->obj()); 4030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(prop->key()); 4031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(LoadDescriptor::ReceiverRegister(), 1 * kPointerSize); 4032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(LoadDescriptor::NameRegister(), 0); 4033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitKeyedPropertyLoad(prop); 4034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We need a second deoptimization point after loading the value 4038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // in case evaluating the property load my have a side effect. 4039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (assign_type == VARIABLE) { 4040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailout(expr->expression(), TOS_REG); 4041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(prop->LoadId(), TOS_REG); 4043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Inline smi case if we are in a loop. 4046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label stub_call, done; 4047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JumpPatchSite patch_site(masm_); 4048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int count_value = expr->op() == Token::INC ? 1 : -1; 4050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (ShouldInlineSmiCase(expr->op())) { 4051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow; 4052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patch_site.EmitJumpIfNotSmi(x0, &slow); 4053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save result for postfix expressions. 4055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->is_postfix()) { 4056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!context()->IsEffect()) { 4057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save the result on the stack. If we have a named or keyed property we 4058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // store the result under the receiver that is currently on top of the 4059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // stack. 4060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (assign_type) { 4061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case VARIABLE: 4062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); 4063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case NAMED_PROPERTY: 4065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Poke(x0, kPointerSize); 4066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case KEYED_PROPERTY: 4068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Poke(x0, kPointerSize * 2); 4069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Adds(x0, x0, Smi::FromInt(count_value)); 4075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(vc, &done); 4076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call stub. Undo operation first. 4077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Sub(x0, x0, Smi::FromInt(count_value)); 4078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&stub_call); 4079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&slow); 4080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ToNumberStub convert_stub(isolate()); 4082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallStub(&convert_stub); 4083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save result for postfix expressions. 4085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->is_postfix()) { 4086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!context()->IsEffect()) { 4087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save the result on the stack. If we have a named or keyed property 4088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // we store the result under the receiver that is currently on top 4089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of the stack. 4090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (assign_type) { 4091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case VARIABLE: 4092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); 4093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case NAMED_PROPERTY: 4095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Poke(x0, kXRegSize); 4096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case KEYED_PROPERTY: 4098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Poke(x0, 2 * kXRegSize); 4099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&stub_call); 4105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x1, x0); 4106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x0, Smi::FromInt(count_value)); 4107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record position before stub call. 4109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetSourcePosition(expr->position()); 4110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 4112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::BlockPoolsScope scope(masm_); 4113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> code = 4114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeFactory::BinaryOpIC(isolate(), Token::ADD, NO_OVERWRITE).code(); 4115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(code, expr->CountBinOpFeedbackId()); 4116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patch_site.EmitPatchInfo(); 4117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 4119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store the value returned in x0. 4121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (assign_type) { 4122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case VARIABLE: 4123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->is_postfix()) { 4124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { EffectContext context(this); 4125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 4126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Token::ASSIGN); 4127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context.Plug(x0); 4129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // For all contexts except EffectConstant We have the result on 4131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // top of the stack. 4132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!context()->IsEffect()) { 4133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PlugTOS(); 4134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 4137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Token::ASSIGN); 4138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 4140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case NAMED_PROPERTY: { 4143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(StoreDescriptor::NameRegister(), 4144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(prop->key()->AsLiteral()->value())); 4145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(StoreDescriptor::ReceiverRegister()); 4146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallStoreIC(expr->CountStoreFeedbackId()); 4147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->is_postfix()) { 4149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!context()->IsEffect()) { 4150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PlugTOS(); 4151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 4154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case KEYED_PROPERTY: { 4158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(StoreDescriptor::NameRegister()); 4159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(StoreDescriptor::ReceiverRegister()); 4160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = 4161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code(); 4162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, expr->CountStoreFeedbackId()); 4163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->is_postfix()) { 4165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!context()->IsEffect()) { 4166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PlugTOS(); 4167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 4170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitForTypeofValue(Expression* expr) { 4178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!context()->IsEffect()); 4179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!context()->IsTest()); 4180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableProxy* proxy = expr->AsVariableProxy(); 4181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (proxy != NULL && proxy->var()->IsUnallocated()) { 4182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "Global variable"); 4183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectMemOperand()); 4184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(LoadDescriptor::NameRegister(), Operand(proxy->name())); 4185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 4186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(VectorLoadICDescriptor::SlotRegister(), 4187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(proxy->VariableFeedbackSlot())); 4188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Use a regular load, not a contextual load, to avoid a reference 4190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // error. 4191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(NOT_CONTEXTUAL); 4192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailout(expr, TOS_REG); 4193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 4194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { 4195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done, slow; 4196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generate code for loading from variables potentially shadowed 4198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // by eval-introduced variables. 4199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitDynamicLookupFastCase(proxy, INSIDE_TYPEOF, &slow, &done); 4200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&slow); 4202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x0, Operand(proxy->name())); 4203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(cp, x0); 4204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kLoadLookupSlotNoReferenceError, 2); 4205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailout(expr, TOS_REG); 4206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 4207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 4209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This expression cannot throw a reference error at the top level. 4211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitInDuplicateContext(expr); 4212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, 4217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* sub_expr, 4218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<String> check) { 4219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof"); 4220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ EmitLiteralCompareTypeof"); 4221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false; 4222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true = NULL; 4223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false = NULL; 4224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through = NULL; 4225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 4226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &if_true, &if_false, &fall_through); 4227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { AccumulatorValueContext context(this); 4229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForTypeofValue(sub_expr); 4230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Factory* factory = isolate()->factory(); 4234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (String::Equals(check, factory->number_string())) { 4235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof number_string"); 4236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x0, if_true); 4237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x0, FieldMemOperand(x0, HeapObject::kMapOffset)); 4238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(x0, Heap::kHeapNumberMapRootIndex); 4239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(eq, if_true, if_false, fall_through); 4240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->string_string())) { 4241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof string_string"); 4242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x0, if_false); 4243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for undetectable objects => false. 4244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfObjectType(x0, x0, x1, FIRST_NONSTRING_TYPE, if_false, ge); 4245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrb(x1, FieldMemOperand(x0, Map::kBitFieldOffset)); 4246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TestAndSplit(x1, 1 << Map::kIsUndetectable, if_true, if_false, 4247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch fall_through); 4248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->symbol_string())) { 4249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof symbol_string"); 4250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x0, if_false); 4251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareObjectType(x0, x0, x1, SYMBOL_TYPE); 4252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(eq, if_true, if_false, fall_through); 4253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->boolean_string())) { 4254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof boolean_string"); 4255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfRoot(x0, Heap::kTrueValueRootIndex, if_true); 4256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(x0, Heap::kFalseValueRootIndex); 4257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(eq, if_true, if_false, fall_through); 4258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->undefined_string())) { 4259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION( 4260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "FullCodeGenerator::EmitLiteralCompareTypeof undefined_string"); 4261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfRoot(x0, Heap::kUndefinedValueRootIndex, if_true); 4262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x0, if_false); 4263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for undetectable objects => true. 4264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x0, FieldMemOperand(x0, HeapObject::kMapOffset)); 4265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrb(x1, FieldMemOperand(x0, Map::kBitFieldOffset)); 4266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TestAndSplit(x1, 1 << Map::kIsUndetectable, if_false, if_true, 4267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch fall_through); 4268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->function_string())) { 4269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof function_string"); 4270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x0, if_false); 4271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); 4272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfObjectType(x0, x10, x11, JS_FUNCTION_TYPE, if_true); 4273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareAndSplit(x11, JS_FUNCTION_PROXY_TYPE, eq, if_true, if_false, 4274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch fall_through); 4275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->object_string())) { 4277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof object_string"); 4278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(x0, if_false); 4279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfRoot(x0, Heap::kNullValueRootIndex, if_true); 4280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for JS objects => true. 4281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register map = x10; 4282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfObjectType(x0, map, x11, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, 4283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if_false, lt); 4284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareInstanceType(map, x11, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); 4285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(gt, if_false); 4286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for undetectable objects => false. 4287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrb(x10, FieldMemOperand(map, Map::kBitFieldOffset)); 4288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TestAndSplit(x10, 1 << Map::kIsUndetectable, if_true, if_false, 4290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch fall_through); 4291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof other"); 4294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (if_false != fall_through) __ B(if_false); 4295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(if_true, if_false); 4297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 4301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ CompareOperation"); 4302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetSourcePosition(expr->position()); 4303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Try to generate an optimized comparison with a literal value. 4305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(jbramley): This only checks common values like NaN or undefined. 4306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Should it also handle ARM64 immediate operands? 4307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (TryLiteralCompare(expr)) { 4308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 4309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Assign labels according to context()->PrepareTest. 4312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true; 4313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_false; 4314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true = NULL; 4315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false = NULL; 4316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through = NULL; 4317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 4318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &if_true, &if_false, &fall_through); 4319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Token::Value op = expr->op(); 4321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(expr->left()); 4322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (op) { 4323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::IN: 4324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(expr->right()); 4325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 4326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); 4327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(x0, Heap::kTrueValueRootIndex); 4328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(eq, if_true, if_false, fall_through); 4329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::INSTANCEOF: { 4332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(expr->right()); 4333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstanceofStub stub(isolate(), InstanceofStub::kNoFlags); 4334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallStub(&stub); 4335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The stub returns 0 for true. 4337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareAndSplit(x0, 0, eq, if_true, if_false, fall_through); 4338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: { 4342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(expr->right()); 4343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond = CompareIC::ComputeCondition(op); 4344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pop the stack value. 4346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(x1); 4347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JumpPatchSite patch_site(masm_); 4349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (ShouldInlineSmiCase(op)) { 4350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow_case; 4351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patch_site.EmitJumpIfEitherNotSmi(x0, x1, &slow_case); 4352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(x1, x0); 4353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(cond, if_true, if_false, NULL); 4354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&slow_case); 4355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record position and call the compare IC. 4358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetSourcePosition(expr->position()); 4359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code(); 4360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, expr->CompareOperationFeedbackId()); 4361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patch_site.EmitPatchInfo(); 4362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareAndSplit(x0, 0, cond, if_true, if_false, fall_through); 4364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Convert the result of the comparison into one expected for this 4368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // expression's context. 4369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(if_true, if_false); 4370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, 4374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* sub_expr, 4375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NilValue nil) { 4376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareNil"); 4377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false; 4378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true = NULL; 4379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false = NULL; 4380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through = NULL; 4381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 4382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &if_true, &if_false, &fall_through); 4383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(sub_expr); 4385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->op() == Token::EQ_STRICT) { 4388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::RootListIndex nil_value = nil == kNullValue ? 4389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::kNullValueRootIndex : 4390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::kUndefinedValueRootIndex; 4391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(x0, nil_value); 4392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(eq, if_true, if_false, fall_through); 4393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); 4395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, expr->CompareOperationFeedbackId()); 4396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareAndSplit(x0, 0, ne, if_true, if_false, fall_through); 4397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(if_true, if_false); 4400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { 4404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 4405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(x0); 4406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitYield(Yield* expr) { 4410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Yield"); 4411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Evaluate yielded value first; the initial iterator definition depends on 4412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // this. It stays on the stack while we update the iterator. 4413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(expr->expression()); 4414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(jbramley): Tidy this up once the merge is done, using named registers 4416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // and suchlike. The implementation changes a little by bleeding_edge so I 4417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // don't want to spend too much time on it now. 4418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (expr->yield_kind()) { 4420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Yield::kSuspend: 4421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pop value from top-of-stack slot; box result into result register. 4422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCreateIteratorResult(false); 4423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(result_register()); 4424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Fall through. 4425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Yield::kInitial: { 4426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label suspend, continuation, post_runtime, resume; 4427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&suspend); 4429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(jbramley): This label is bound here because the following code 4431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // looks at its pos(). Is it possible to do something more efficient here, 4432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // perhaps using Adr? 4433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&continuation); 4434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&resume); 4435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&suspend); 4437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(expr->generator_object()); 4438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((continuation.pos() > 0) && Smi::IsValid(continuation.pos())); 4439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x1, Smi::FromInt(continuation.pos())); 4440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(x1, FieldMemOperand(x0, JSGeneratorObject::kContinuationOffset)); 4441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(cp, FieldMemOperand(x0, JSGeneratorObject::kContextOffset)); 4442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x1, cp); 4443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteField(x0, JSGeneratorObject::kContextOffset, x1, x2, 4444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kLRHasBeenSaved, kDontSaveFPRegs); 4445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Add(x1, fp, StandardFrameConstants::kExpressionsOffset); 4446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(__ StackPointer(), x1); 4447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(eq, &post_runtime); 4448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); // generator object 4449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); 4450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 4451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&post_runtime); 4452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(result_register()); 4453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitReturnSequence(); 4454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&resume); 4456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(result_register()); 4457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Yield::kFinal: { 4461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(expr->generator_object()); 4462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x1, Smi::FromInt(JSGeneratorObject::kGeneratorClosed)); 4463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(x1, FieldMemOperand(result_register(), 4464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSGeneratorObject::kContinuationOffset)); 4465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pop value from top-of-stack slot, box result into result register. 4466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCreateIteratorResult(true); 4467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitUnwindBeforeReturn(); 4468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitReturnSequence(); 4469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Yield::kDelegating: { 4473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(expr->generator_object()); 4474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Initial stack layout is as follows: 4476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // [sp + 1 * kPointerSize] iter 4477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // [sp + 0 * kPointerSize] g 4478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label l_catch, l_try, l_suspend, l_continuation, l_resume; 4480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label l_next, l_call, l_loop; 4481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register load_receiver = LoadDescriptor::ReceiverRegister(); 4482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register load_name = LoadDescriptor::NameRegister(); 4483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Initial send value is undefined. 4485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); 4486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&l_next); 4487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } 4489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&l_catch); 4490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); 4491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(load_name, Heap::kthrow_stringRootIndex); // "throw" 4492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(x3, 1 * kPointerSize); // iter 4493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(load_name, x3, x0); // "throw", iter, except 4494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&l_call); 4495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // try { received = %yield result } 4497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Shuffle the received result above a try handler and yield it without 4498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // re-boxing. 4499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&l_try); 4500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(x0); // result 4501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushTryHandler(StackHandler::CATCH, expr->index()); 4502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int handler_size = StackHandlerConstants::kSize; 4503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); // result 4504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&l_suspend); 4505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(jbramley): This label is bound here because the following code 4507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // looks at its pos(). Is it possible to do something more efficient here, 4508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // perhaps using Adr? 4509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&l_continuation); 4510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&l_resume); 4511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&l_suspend); 4513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int generator_object_depth = kPointerSize + handler_size; 4514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(x0, generator_object_depth); 4515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x0); // g 4516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((l_continuation.pos() > 0) && Smi::IsValid(l_continuation.pos())); 4517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x1, Smi::FromInt(l_continuation.pos())); 4518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(x1, FieldMemOperand(x0, JSGeneratorObject::kContinuationOffset)); 4519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(cp, FieldMemOperand(x0, JSGeneratorObject::kContextOffset)); 4520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x1, cp); 4521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteField(x0, JSGeneratorObject::kContextOffset, x1, x2, 4522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kLRHasBeenSaved, kDontSaveFPRegs); 4523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); 4524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 4525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(x0); // result 4526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitReturnSequence(); 4527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&l_resume); // received in x0 4528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PopTryHandler(); 4529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // receiver = iter; f = 'next'; arg = received; 4531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&l_next); 4532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(load_name, Heap::knext_stringRootIndex); // "next" 4534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(x3, 1 * kPointerSize); // iter 4535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(load_name, x3, x0); // "next", iter, received 4536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // result = receiver[f](arg); 4538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&l_call); 4539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(load_receiver, 1 * kPointerSize); 4540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(load_name, 2 * kPointerSize); 4541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 4542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(VectorLoadICDescriptor::SlotRegister(), 4543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(expr->KeyedLoadFeedbackSlot())); 4544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code(); 4546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, TypeFeedbackId::None()); 4547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x1, x0); 4548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Poke(x1, 2 * kPointerSize); 4549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD); 4550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallStub(&stub); 4551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 4553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Drop(1); // The function is still on the stack; drop it. 4554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // if (!result.done) goto l_try; 4556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&l_loop); 4557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(load_receiver, x0); 4558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(load_receiver); // save result 4560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done" 4561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 4562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(VectorLoadICDescriptor::SlotRegister(), 4563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(expr->DoneFeedbackSlot())); 4564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(NOT_CONTEXTUAL); // x0=result.done 4566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The ToBooleanStub argument (result.done) is in x0. 4567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); 4568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(bool_ic); 4569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cbz(x0, &l_try); 4570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // result.value 4572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(load_receiver); // result 4573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value" 4574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 4575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(VectorLoadICDescriptor::SlotRegister(), 4576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(expr->ValueFeedbackSlot())); 4577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(NOT_CONTEXTUAL); // x0=result.value 4579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->DropAndPlug(2, x0); // drop iter and g 4580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitGeneratorResume(Expression *generator, 4587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression *value, 4588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSGeneratorObject::ResumeMode resume_mode) { 4589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EmitGeneratorResume"); 4590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value_reg = x0; 4591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register generator_object = x1; 4592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register the_hole = x2; 4593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register operand_stack_size = w3; 4594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register function = x4; 4595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The value stays in x0, and is ultimately read by the resumed generator, as 4597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it 4598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is read to throw the value when the resumed generator is already closed. r1 4599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // will hold the generator object until the activation has been resumed. 4600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(generator); 4601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(value); 4602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(generator_object); 4603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check generator state. 4605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label wrong_state, closed_state, done; 4606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x10, FieldMemOperand(generator_object, 4607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSGeneratorObject::kContinuationOffset)); 4608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0); 4609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0); 4610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareAndBranch(x10, Smi::FromInt(0), eq, &closed_state); 4611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareAndBranch(x10, Smi::FromInt(0), lt, &wrong_state); 4612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load suspended function and context. 4614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(cp, FieldMemOperand(generator_object, 4615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSGeneratorObject::kContextOffset)); 4616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(function, FieldMemOperand(generator_object, 4617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSGeneratorObject::kFunctionOffset)); 4618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load receiver and store as the first argument. 4620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x10, FieldMemOperand(generator_object, 4621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSGeneratorObject::kReceiverOffset)); 4622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x10); 4623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push holes for the rest of the arguments to the generator function. 4625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x10, FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset)); 4626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The number of arguments is stored as an int32_t, and -1 is a marker 4628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (SharedFunctionInfo::kDontAdaptArgumentsSentinel), so we need sign 4629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // extension to correctly handle it. However, in this case, we operate on 4630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 32-bit W registers, so extension isn't required. 4631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(w10, FieldMemOperand(x10, 4632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedFunctionInfo::kFormalParameterCountOffset)); 4633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(the_hole, Heap::kTheHoleValueRootIndex); 4634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushMultipleTimes(the_hole, w10); 4635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Enter a new JavaScript frame, and initialize its slots as they were when 4637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the generator was suspended. 4638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label resume_frame; 4639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bl(&resume_frame); 4640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 4641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&resume_frame); 4643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(lr, // Return address. 4644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch fp, // Caller's frame pointer. 4645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cp, // Callee's context. 4646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch function); // Callee's JS Function. 4647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Add(fp, __ StackPointer(), kPointerSize * 2); 4648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load and untag the operand stack size. 4650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x10, FieldMemOperand(generator_object, 4651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSGeneratorObject::kOperandStackOffset)); 4652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(operand_stack_size, 4653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UntagSmiFieldMemOperand(x10, FixedArray::kLengthOffset)); 4654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we are sending a value and there is no operand stack, we can jump back 4656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // in directly. 4657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (resume_mode == JSGeneratorObject::NEXT) { 4658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow_resume; 4659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cbnz(operand_stack_size, &slow_resume); 4660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x10, FieldMemOperand(function, JSFunction::kCodeEntryOffset)); 4661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrsw(x11, 4662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UntagSmiFieldMemOperand(generator_object, 4663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSGeneratorObject::kContinuationOffset)); 4664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Add(x10, x10, x11); 4665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x12, Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)); 4666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(x12, FieldMemOperand(generator_object, 4667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSGeneratorObject::kContinuationOffset)); 4668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Br(x10); 4669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&slow_resume); 4671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Otherwise, we push holes for the operand stack and call the runtime to fix 4674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // up the stack and the handlers. 4675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushMultipleTimes(the_hole, operand_stack_size); 4676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x10, Smi::FromInt(resume_mode)); 4678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(generator_object, result_register(), x10); 4679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); 4680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Not reached: the runtime call returns elsewhere. 4681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Unreachable(); 4682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Reach here when generator is closed. 4684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&closed_state); 4685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (resume_mode == JSGeneratorObject::NEXT) { 4686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return completed iterator result when generator is closed. 4687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(x10, Heap::kUndefinedValueRootIndex); 4688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x10); 4689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pop value from top-of-stack slot; box result into result register. 4690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCreateIteratorResult(true); 4691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Throw the provided value. 4693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(value_reg); 4694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kThrow, 1); 4695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&done); 4697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Throw error if we attempt to operate on a running generator. 4699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&wrong_state); 4700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(generator_object); 4701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); 4702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 4704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(result_register()); 4705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCreateIteratorResult(bool done) { 4709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label gc_required; 4710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label allocated; 4711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> map(isolate()->native_context()->iterator_result_map()); 4713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Allocate and populate an object with this form: { value: VAL, done: DONE } 4715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = x0; 4717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Allocate(map->instance_size(), result, x10, x11, &gc_required, TAG_OBJECT); 4718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&allocated); 4719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&gc_required); 4721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Smi::FromInt(map->instance_size())); 4722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kAllocateInNewSpace, 1); 4723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(context_register(), 4724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand(fp, StandardFrameConstants::kContextOffset)); 4725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&allocated); 4727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register map_reg = x1; 4728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result_value = x2; 4729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register boolean_done = x3; 4730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register empty_fixed_array = x4; 4731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register untagged_result = x5; 4732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(map_reg, Operand(map)); 4733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(result_value); 4734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(boolean_done, Operand(isolate()->factory()->ToBoolean(done))); 4735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(empty_fixed_array, Operand(isolate()->factory()->empty_fixed_array())); 4736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(map->instance_size(), 5 * kPointerSize); 4737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(JSObject::kPropertiesOffset + kPointerSize == 4738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSObject::kElementsOffset); 4739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(JSGeneratorObject::kResultValuePropertyOffset + kPointerSize == 4740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSGeneratorObject::kResultDonePropertyOffset); 4741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ObjectUntag(untagged_result, result); 4742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(map_reg, MemOperand(untagged_result, HeapObject::kMapOffset)); 4743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Stp(empty_fixed_array, empty_fixed_array, 4744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand(untagged_result, JSObject::kPropertiesOffset)); 4745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Stp(result_value, boolean_done, 4746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand(untagged_result, 4747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSGeneratorObject::kResultValuePropertyOffset)); 4748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Only the value field needs a write barrier, as the other values are in the 4750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // root set. 4751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteField(result, JSGeneratorObject::kResultValuePropertyOffset, 4752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x10, x11, kLRHasBeenSaved, kDontSaveFPRegs); 4753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// TODO(all): I don't like this method. 4757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// It seems to me that in too many places x0 is used in place of this. 4758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Also, this function is not suitable for all places where x0 should be 4759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// abstracted (eg. when used as an argument). But some places assume that the 4760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// first argument register is x0, and use this function instead. 4761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Considering that most of the register allocation is hard-coded in the 4762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// FullCodeGen, that it is unlikely we will need to change it extensively, and 4763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// that abstracting the allocation through functions would not yield any 4764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// performance benefit, I think the existence of this function is debatable. 4765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister FullCodeGenerator::result_register() { 4766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return x0; 4767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister FullCodeGenerator::context_register() { 4771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return cp; 4772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 4776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(POINTER_SIZE_ALIGN(frame_offset) == frame_offset); 4777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(value, MemOperand(fp, frame_offset)); 4778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::LoadContextField(Register dst, int context_index) { 4782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(dst, ContextMemOperand(cp, context_index)); 4783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::PushFunctionArgumentForContextAllocation() { 4787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Scope* declaration_scope = scope()->DeclarationScope(); 4788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (declaration_scope->is_global_scope() || 4789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch declaration_scope->is_module_scope()) { 4790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Contexts nested in the native context have a canonical empty function 4791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // as their closure, not the anonymous closure containing the global 4792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // code. Pass a smi sentinel and let the runtime look up the empty 4793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // function. 4794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(kSmiTag == 0); 4795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(xzr); 4796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (declaration_scope->is_eval_scope()) { 4797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Contexts created by a call to eval have the same closure as the 4798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // context calling eval, not the anonymous closure containing the eval 4799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // code. Fetch it from the context. 4800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x10, ContextMemOperand(cp, Context::CLOSURE_INDEX)); 4801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x10); 4802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(declaration_scope->is_function_scope()); 4804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x10, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 4805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x10); 4806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EnterFinallyBlock() { 4811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::EnterFinallyBlock"); 4812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!result_register().is(x10)); 4813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Preserve the result register while executing finally block. 4814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Also cook the return address in lr to the stack (smi encoded Code* delta). 4815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Sub(x10, lr, Operand(masm_->CodeObject())); 4816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(x10); 4817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(result_register(), x10); 4818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store pending message while executing finally block. 4820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference pending_message_obj = 4821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_pending_message_obj(isolate()); 4822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x10, pending_message_obj); 4823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x10, MemOperand(x10)); 4824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference has_pending_message = 4826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_has_pending_message(isolate()); 4827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(sizeof(bool) == 1); // NOLINT(runtime/sizeof) 4828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x11, has_pending_message); 4829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrb(x11, MemOperand(x11)); 4830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(x11); 4831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x10, x11); 4833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference pending_message_script = 4835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_pending_message_script(isolate()); 4836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x10, pending_message_script); 4837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(x10, MemOperand(x10)); 4838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(x10); 4839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::ExitFinallyBlock() { 4843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::ExitFinallyBlock"); 4844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!result_register().is(x10)); 4845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore pending message from stack. 4847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(x10, x11, x12); 4848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference pending_message_script = 4849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_pending_message_script(isolate()); 4850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x13, pending_message_script); 4851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(x10, MemOperand(x13)); 4852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(x11); 4854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference has_pending_message = 4855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_has_pending_message(isolate()); 4856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x13, has_pending_message); 4857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(sizeof(bool) == 1); // NOLINT(runtime/sizeof) 4858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Strb(x11, MemOperand(x13)); 4859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference pending_message_obj = 4861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_pending_message_obj(isolate()); 4862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x13, pending_message_obj); 4863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(x12, MemOperand(x13)); 4864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore result register and cooked return address from the stack. 4866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(x10, result_register()); 4867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Uncook the return address (see EnterFinallyBlock). 4869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(x10); 4870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Add(x11, x10, Operand(masm_->CodeObject())); 4871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Br(x11); 4872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __ 4876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid BackEdgeTable::PatchAt(Code* unoptimized_code, 4879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address pc, 4880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BackEdgeState target_state, 4881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code* replacement_code) { 4882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Turn the jump into a nop. 4883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address branch_address = pc - 3 * kInstructionSize; 4884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PatchingAssembler patcher(branch_address, 1); 4885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Instruction::Cast(branch_address) 4887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ->IsNop(Assembler::INTERRUPT_CODE_NOP) || 4888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (Instruction::Cast(branch_address)->IsCondBranchImm() && 4889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction::Cast(branch_address)->ImmPCOffset() == 4890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6 * kInstructionSize)); 4891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (target_state) { 4893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case INTERRUPT: 4894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // <decrement profiling counter> 4895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // .. .. .. .. b.pl ok 4896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // .. .. .. .. ldr x16, pc+<interrupt stub address> 4897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // .. .. .. .. blr x16 4898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ... more instructions. 4899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ok-label 4900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Jump offset is 6 instructions. 4901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patcher.b(6, pl); 4902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case ON_STACK_REPLACEMENT: 4904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case OSR_AFTER_STACK_CHECK: 4905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // <decrement profiling counter> 4906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // .. .. .. .. mov x0, x0 (NOP) 4907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // .. .. .. .. ldr x16, pc+<on-stack replacement address> 4908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // .. .. .. .. blr x16 4909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patcher.nop(Assembler::INTERRUPT_CODE_NOP); 4910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Replace the call address. 4914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction* load = Instruction::Cast(pc)->preceding(2); 4915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address interrupt_address_pointer = 4916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<Address>(load) + load->ImmPCOffset(); 4917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((Memory::uint64_at(interrupt_address_pointer) == 4918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<uint64_t>(unoptimized_code->GetIsolate() 4919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ->builtins() 4920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ->OnStackReplacement() 4921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ->entry())) || 4922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (Memory::uint64_at(interrupt_address_pointer) == 4923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<uint64_t>(unoptimized_code->GetIsolate() 4924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ->builtins() 4925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ->InterruptCheck() 4926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ->entry())) || 4927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (Memory::uint64_at(interrupt_address_pointer) == 4928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<uint64_t>(unoptimized_code->GetIsolate() 4929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ->builtins() 4930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ->OsrAfterStackCheck() 4931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ->entry())) || 4932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (Memory::uint64_at(interrupt_address_pointer) == 4933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<uint64_t>(unoptimized_code->GetIsolate() 4934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ->builtins() 4935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ->OnStackReplacement() 4936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ->entry()))); 4937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Memory::uint64_at(interrupt_address_pointer) = 4938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<uint64_t>(replacement_code->entry()); 4939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch( 4941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unoptimized_code, reinterpret_cast<Address>(load), replacement_code); 4942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochBackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState( 4946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate, 4947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code* unoptimized_code, 4948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address pc) { 4949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(jbramley): There should be some extra assertions here (as in the ARM 4950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // back-end), but this function is gone in bleeding_edge so it might not 4951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // matter anyway. 4952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction* jump_or_nop = Instruction::Cast(pc)->preceding(3); 4953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (jump_or_nop->IsNop(Assembler::INTERRUPT_CODE_NOP)) { 4955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction* load = Instruction::Cast(pc)->preceding(2); 4956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t entry = Memory::uint64_at(reinterpret_cast<Address>(load) + 4957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch load->ImmPCOffset()); 4958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (entry == reinterpret_cast<uint64_t>( 4959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate->builtins()->OnStackReplacement()->entry())) { 4960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return ON_STACK_REPLACEMENT; 4961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (entry == reinterpret_cast<uint64_t>( 4962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate->builtins()->OsrAfterStackCheck()->entry())) { 4963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return OSR_AFTER_STACK_CHECK; 4964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 4966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return INTERRUPT; 4970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ ACCESS_MASM(masm()) 4974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochFullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit( 4977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int* stack_depth, 4978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int* context_length) { 4979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("FullCodeGenerator::TryFinally::Exit"); 4980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The macros used here must preserve the result register. 4981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Because the handler block contains the context of the finally 4983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // code, we can restore it directly from there for the finally code 4984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rather than iteratively unwinding contexts via their previous 4985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // links. 4986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Drop(*stack_depth); // Down to the handler block. 4987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (*context_length > 0) { 4988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore the context to its dedicated register and the stack. 4989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Peek(cp, StackHandlerConstants::kContextOffset); 4990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 4991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PopTryHandler(); 4993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bl(finally_entry_); 4994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *stack_depth = 0; 4996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *context_length = 0; 4997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return previous_; 4998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __ 5002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} } // namespace v8::internal 5005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // V8_TARGET_ARCH_ARM64 5007