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