13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h" 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_ARM 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-factory.h" 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-stubs.h" 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h" 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler.h" 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/debug.h" 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/full-codegen.h" 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/ic.h" 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/isolate-inl.h" 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/parser.h" 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/scopes.h" 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm/code-stubs-arm.h" 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm/macro-assembler-arm.h" 229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace v8 { 243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace internal { 253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#define __ ACCESS_MASM(masm_) 273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// A patch site is a location in the code which it is possible to patch. This 301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// class has a number of methods to emit the code which is patchable and the 311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// method EmitPatchInfo to record a marker back to the patchable code. This 321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// marker is a cmp rx, #yyy instruction, and x * 0x00000fff + yyy (raw 12 bit 331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// immediate value is used) is the delta from the pc to the first instruction of 341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// the patchable code. 351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockclass JumpPatchSite BASE_EMBEDDED { 361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public: 371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) { 381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG 391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block info_emitted_ = false; 401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif 411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ~JumpPatchSite() { 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(patch_site_.is_bound() == info_emitted_); 451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // When initially emitting this ensure that a jump is always generated to skip 481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the inlined smi code. 491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void EmitJumpIfNotSmi(Register reg, Label* target) { 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!patch_site_.is_bound() && !info_emitted_); 51db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch Assembler::BlockConstPoolScope block_const_pool(masm_); 521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&patch_site_); 531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmp(reg, Operand(reg)); 541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(eq, target); // Always taken before patched. 551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // When initially emitting this ensure that a jump is never generated to skip 581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the inlined smi code. 591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void EmitJumpIfSmi(Register reg, Label* target) { 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!patch_site_.is_bound() && !info_emitted_); 61db1b4389239a7132c9cde0915dbd3f775dc1027aBen Murdoch Assembler::BlockConstPoolScope block_const_pool(masm_); 621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&patch_site_); 631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmp(reg, Operand(reg)); 641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(ne, target); // Never taken before patched. 651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void EmitPatchInfo() { 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Block literal pool emission whilst recording patch site information. 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::BlockConstPoolScope block_const_pool(masm_); 703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (patch_site_.is_bound()) { 713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int delta_to_patch_site = masm_->InstructionsGeneratedSince(&patch_site_); 723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register reg; 733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch reg.set_code(delta_to_patch_site / kOff12Mask); 743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp_raw_immediate(reg, delta_to_patch_site % kOff12Mask); 751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG 763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch info_emitted_ = true; 771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif 783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ nop(); // Signals no inlined code. 803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private: 841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block MacroAssembler* masm_; 851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label patch_site_; 861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG 871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool info_emitted_; 881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif 891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}; 901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Generate code for a JS function. On entry to the function the receiver 933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// and arguments have been pushed on the stack left to right. The actual 943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// argument count matches the formal parameter count expected by the 953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// function. 963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The live registers are: 983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// o r1: the JS function object being called (i.e., ourselves) 993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o cp: our context 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// o pp: our caller's constant pool pointer (if FLAG_enable_ool_constant_pool) 1013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o fp: our caller's frame pointer 1023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o sp: stack pointer 1033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o lr: return address 1043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 1053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame. Please see JavaScriptFrameConstants in 1063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-arm.h for its layout. 1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::Generate() { 1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompilationInfo* info = info_; 1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch handler_table_ = 1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED); 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch profiling_counter_ = isolate()->factory()->NewCell( 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate())); 1143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SetFunctionPosition(function()); 1156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Comment cmnt(masm_, "[ function compiled by full code generator"); 1163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ProfileEntryHookStub::MaybeCallEntryHook(masm_); 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 119f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#ifdef DEBUG 120f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if (strlen(FLAG_stop_at) > 0 && 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { 122f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ stop("stop-at"); 123f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch } 124f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#endif 125f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Sloppy mode functions and builtins need to replace the receiver with the 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // global proxy when called as functions (without an explicit receiver 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // object). 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (info->strict_mode() == SLOPPY && !info->is_native()) { 130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label ok; 1313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int receiver_offset = info->scope()->num_parameters() * kPointerSize; 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r2, MemOperand(sp, receiver_offset)); 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(r2, Heap::kUndefinedValueRootIndex); 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, &ok); 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r2, GlobalObjectOperand()); 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalProxyOffset)); 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ str(r2, MemOperand(sp, receiver_offset)); 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&ok); 142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Open a frame scope to indicate that there is a frame on the stack. The 1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // MANUAL indicates that the scope shouldn't actually generate code to set up 1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the frame (that is done below). 1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope frame_scope(masm_, StackFrame::MANUAL); 1483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info->set_prologue_offset(masm_->pc_offset()); 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Prologue(info->IsCodePreAgingActive()); 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info->AddNoFrameRange(0, masm_->pc_offset()); 1523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 153756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick { Comment cmnt(masm_, "[ Allocate locals"); 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int locals_count = info->scope()->num_stack_slots(); 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generators allocate locals, if any, in context slots. 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!info->function()->is_generator() || locals_count == 0); 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (locals_count > 0) { 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (locals_count >= 128) { 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label ok; 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(r9, sp, Operand(locals_count * kPointerSize)); 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(r2, Heap::kRealStackLimitRootIndex); 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r9, Operand(r2)); 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(hs, &ok); 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&ok); 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(r9, Heap::kUndefinedValueRootIndex); 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int kMaxPushes = FLAG_optimize_for_size ? 4 : 32; 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (locals_count >= kMaxPushes) { 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int loop_iterations = locals_count / kMaxPushes; 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r2, Operand(loop_iterations)); 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label loop_header; 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&loop_header); 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do pushes. 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < kMaxPushes; i++) { 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r9); 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Continue loop if not done. 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(r2, r2, Operand(1), SetCC); 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(&loop_header, ne); 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int remaining = locals_count % kMaxPushes; 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit the remaining pushes. 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < remaining; i++) { 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r9); 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1874515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 188756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 189d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 190756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick bool function_in_register = true; 1914515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 192756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Possibly allocate a local context. 1933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 194756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (heap_slots > 0) { 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Argument to NewContext is the function, which is still in r1. 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Allocate context"); 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool need_write_barrier = true; 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_harmony_scoping && info->scope()->is_global_scope()) { 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r1); 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(info->scope()->GetScopeInfo()); 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kNewGlobalContext, 2); 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (heap_slots <= FastNewContextStub::kMaximumSlots) { 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FastNewContextStub stub(isolate(), heap_slots); 204756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ CallStub(&stub); 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Result of FastNewContextStub is always in new space. 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch need_write_barrier = false; 207756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else { 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r1); 2093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CallRuntime(Runtime::kNewFunctionContext, 1); 210756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 211756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick function_in_register = false; 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Context is returned in r0. It replaces the context passed to us. 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // It's saved in the stack and kept live in cp. 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(cp, r0); 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r0, MemOperand(fp, StandardFrameConstants::kContextOffset)); 216756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Copy any necessary parameters into the context. 2173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int num_parameters = info->scope()->num_parameters(); 218756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick for (int i = 0; i < num_parameters; i++) { 219589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* var = scope()->parameter(i); 220589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsContextSlot()) { 221756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick int parameter_offset = StandardFrameConstants::kCallerSPOffset + 222756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick (num_parameters - 1 - i) * kPointerSize; 223756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Load parameter from stack. 224756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ ldr(r0, MemOperand(fp, parameter_offset)); 225756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Store it in the context. 2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MemOperand target = ContextOperand(cp, var->index()); 2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r0, target); 2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Update the write barrier. 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (need_write_barrier) { 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteContextSlot( 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cp, target.offset(), r0, r3, kLRHasBeenSaved, kDontSaveFPRegs); 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (FLAG_debug_code) { 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfInNewSpace(cp, r0, &done); 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Abort(kExpectedNewSpaceObject); 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 240d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 241756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 242d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Variable* arguments = scope()->arguments(); 244756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (arguments != NULL) { 245756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Function uses arguments object. 246756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Comment cmnt(masm_, "[ Allocate arguments object"); 247756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (!function_in_register) { 248756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Load this again, if it's used by the local context below. 249756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 250756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else { 251756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ mov(r3, r1); 252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 253756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Receiver is just before the parameters on the caller's stack. 2543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int num_parameters = info->scope()->num_parameters(); 2553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int offset = num_parameters * kPointerSize; 256756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ add(r2, fp, 257756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Operand(StandardFrameConstants::kCallerSPOffset + offset)); 2583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(r1, Operand(Smi::FromInt(num_parameters))); 259756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ Push(r3, r2, r1); 260756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 261756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Arguments to ArgumentsAccessStub: 262756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // function, receiver address, parameter count. 263756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // The stub will rewrite receiever and parameter count if the previous 264756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // stack frame was an arguments adapter frame. 2653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ArgumentsAccessStub::Type type; 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (strict_mode() == STRICT) { 2673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch type = ArgumentsAccessStub::NEW_STRICT; 2683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else if (function()->has_duplicate_parameters()) { 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch type = ArgumentsAccessStub::NEW_SLOPPY_SLOW; 2703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch type = ArgumentsAccessStub::NEW_SLOPPY_FAST; 2723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArgumentsAccessStub stub(isolate(), type); 274756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ CallStub(&stub); 27544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 276589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch SetVar(arguments, r0, r1, r2); 277d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 278d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace) { 280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ CallRuntime(Runtime::kTraceEnter, 0); 281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 283e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Visit the declarations and body unless there is an illegal 284e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // redeclaration. 285e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (scope()->HasIllegalRedeclaration()) { 286e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Comment cmnt(masm_, "[ Declarations"); 287e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch scope()->VisitIllegalRedeclaration(this); 2883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 289e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); 291e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch { Comment cmnt(masm_, "[ Declarations"); 292e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // For named function expressions, declare the function name as a 293e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // constant. 294e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (scope()->is_function_scope() && scope()->function() != NULL) { 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableDeclaration* function = scope()->function(); 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(function->proxy()->var()->mode() == CONST || 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch function->proxy()->var()->mode() == CONST_LEGACY); 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(function->proxy()->var()->location() != Variable::UNALLOCATED); 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitVariableDeclaration(function); 300e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitDeclarations(scope()->declarations()); 302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 304e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch { Comment cmnt(masm_, "[ Stack check"); 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); 306e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Label ok; 307e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ LoadRoot(ip, Heap::kStackLimitRootIndex); 308e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmp(sp, Operand(ip)); 309e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(hs, &ok); 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> stack_check = isolate()->builtins()->StackCheck(); 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PredictableCodeSizeScope predictable(masm_, 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm_->CallSize(stack_check, RelocInfo::CODE_TARGET)); 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Call(stack_check, RelocInfo::CODE_TARGET); 314e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&ok); 315e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 316e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 317e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch { Comment cmnt(masm_, "[ Body"); 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(loop_depth() == 0); 319e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitStatements(function()->body()); 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(loop_depth() == 0); 321e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 3233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 324e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Always emit a 'return undefined' in case control fell off the end of 325e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // the body. 3263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ return <undefined>;"); 3273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 328d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch EmitReturnSequence(); 330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Force emit the constant pool, so it doesn't get emitted in the middle 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of the back edge table. 333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch masm()->CheckConstPool(true, false); 334d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 335d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 336d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 337db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdochvoid FullCodeGenerator::ClearAccumulator() { 338db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch __ mov(r0, Operand(Smi::FromInt(0))); 339db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch} 340db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch 341db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch 3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitProfilingCounterDecrement(int delta) { 3433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r2, Operand(profiling_counter_)); 344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset)); 3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(r3, r3, Operand(Smi::FromInt(delta)), SetCC); 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r3, FieldMemOperand(r2, Cell::kValueOffset)); 3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef CAN_USE_ARMV7_INSTRUCTIONS 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const int kProfileCounterResetSequenceLength = 5 * Assembler::kInstrSize; 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const int kProfileCounterResetSequenceLength = 7 * Assembler::kInstrSize; 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitProfilingCounterReset() { 358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::BlockConstPoolScope block_const_pool(masm_); 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PredictableCodeSizeScope predictable_code_size_scope( 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm_, kProfileCounterResetSequenceLength); 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label start; 362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&start); 3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int reset_value = FLAG_interrupt_budget; 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (info_->is_debug()) { 3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Detect debug break requests as soon as possible. 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reset_value = FLAG_interrupt_budget >> 4; 3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r2, Operand(profiling_counter_)); 369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The mov instruction above can be either 1 to 3 (for ARMv7) or 1 to 5 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // instructions (for ARMv6) depending upon whether it is an extended constant 371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // pool - insert nop to compensate. 372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int expected_instr_count = 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (kProfileCounterResetSequenceLength / Assembler::kInstrSize) - 2; 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(masm_->InstructionsGeneratedSince(&start) <= expected_instr_count); 375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (masm_->InstructionsGeneratedSince(&start) != expected_instr_count) { 376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ nop(); 377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r3, Operand(Smi::FromInt(reset_value))); 379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r3, FieldMemOperand(r2, Cell::kValueOffset)); 3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt, 384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* back_edge_target) { 385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Back edge bookkeeping"); 386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Block literal pools whilst emitting back edge code. 387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::BlockConstPoolScope block_const_pool(masm_); 388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label ok; 3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(back_edge_target->is_bound()); 391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); 392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int weight = Min(kMaxBackEdgeWeight, 393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Max(1, distance / kCodeSizeMultiplier)); 394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitProfilingCounterDecrement(weight); 395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(pl, &ok); 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET); 3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 398086aeeaae12517475c22695a200be45495516549Ben Murdoch // Record a mapping of this PC offset to the OSR id. This is used to find 399086aeeaae12517475c22695a200be45495516549Ben Murdoch // the AST id from the unoptimized code in order to use it as a key into 400086aeeaae12517475c22695a200be45495516549Ben Murdoch // the deoptimization input data found in the optimized code. 401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordBackEdge(stmt->OsrEntryId()); 402086aeeaae12517475c22695a200be45495516549Ben Murdoch 403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitProfilingCounterReset(); 4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&ok); 406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); 407086aeeaae12517475c22695a200be45495516549Ben Murdoch // Record a mapping of the OSR id to this PC. This is used if the OSR 408086aeeaae12517475c22695a200be45495516549Ben Murdoch // entry becomes the target of a bailout. We don't expect it to be, but 409086aeeaae12517475c22695a200be45495516549Ben Murdoch // we want it to work if it is. 410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS); 411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitReturnSequence() { 415d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Return sequence"); 416d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (return_label_.is_bound()) { 417d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ b(&return_label_); 418d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 419d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&return_label_); 4203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (FLAG_trace) { 4213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Push the return value on the stack as the parameter. 4223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Runtime::TraceExit returns its parameter in r0. 4233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(r0); 4243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kTraceExit, 1); 4253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pretend that the exit is a backwards jump to the entry. 427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int weight = 1; 428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (info_->ShouldSelfOptimize()) { 429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch weight = FLAG_interrupt_budget / FLAG_self_opt_count; 430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int distance = masm_->pc_offset(); 432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch weight = Min(kMaxBackEdgeWeight, 433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Max(1, distance / kCodeSizeMultiplier)); 4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitProfilingCounterDecrement(weight); 436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label ok; 437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(pl, &ok); 438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r0); 439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Call(isolate()->builtins()->InterruptCheck(), 440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RelocInfo::CODE_TARGET); 441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(r0); 442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitProfilingCounterReset(); 443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&ok); 4443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef DEBUG 446d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Add a label for checking the size of the code used for returning. 447d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label check_exit_codesize; 448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&check_exit_codesize); 4496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif 4506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Make sure that the constant pool is not emitted inside of the return 4516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // sequence. 4526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block { Assembler::BlockConstPoolScope block_const_pool(masm_); 4533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int32_t sp_delta = (info_->scope()->num_parameters() + 1) * kPointerSize; 454bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch CodeGenerator::RecordPositions(masm_, function()->end_position() - 1); 455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(svenpanne) The code below is sometimes 4 words, sometimes 5! 456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PredictableCodeSizeScope predictable(masm_, -1); 4576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ RecordJSReturn(); 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int no_frame_start = __ LeaveFrame(StackFrame::JAVA_SCRIPT); 459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { ConstantPoolUnavailableScope constant_pool_unavailable(masm_); 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(sp, sp, Operand(sp_delta)); 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Jump(lr); 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); 463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 464d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 465d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef DEBUG 4671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the size of the code used for returning is large enough 4681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // for the debugger's requirements. 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::kJSReturnSequenceInstructions <= 4701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block masm_->InstructionsGeneratedSince(&check_exit_codesize)); 4716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif 472d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 473d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 474d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 475d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 476589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::EffectContext::Plug(Variable* var) const { 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 4780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 479e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 480e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 481589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const { 482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 483589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch codegen()->GetVar(result_register(), var); 4840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 485e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 487589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::StackValueContext::Plug(Variable* var) const { 488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 489589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch codegen()->GetVar(result_register(), var); 4900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(result_register()); 491d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 492d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 493d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 494589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::TestContext::Plug(Variable* var) const { 495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 4960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // For simplicity we always test the accumulator register. 497589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch codegen()->GetVar(result_register(), var); 4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); 4993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch codegen()->DoTest(this); 500d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 501d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 502d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 5030d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { 5040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 5050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5070d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug( 5080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex index) const { 5090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), index); 5100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 5110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5130d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug( 5140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex index) const { 5150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), index); 5160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(result_register()); 5170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 5180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5200d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const { 5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), 522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true, 523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true_label_, 524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch false_label_); 5250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (index == Heap::kUndefinedValueRootIndex || 5260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen index == Heap::kNullValueRootIndex || 5270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen index == Heap::kFalseValueRootIndex) { 528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (false_label_ != fall_through_) __ b(false_label_); 5290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (index == Heap::kTrueValueRootIndex) { 530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (true_label_ != fall_through_) __ b(true_label_); 5310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 5320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), index); 5333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch codegen()->DoTest(this); 534e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 535d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 536d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 537d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 5380d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const { 5390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 540e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 541e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 5420d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug( 5430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Handle<Object> lit) const { 5440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(result_register(), Operand(lit)); 5450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 546e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 5470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5480d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { 549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Immediates cannot be pushed directly. 5500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(result_register(), Operand(lit)); 5510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(result_register()); 5520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 5530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5550d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { 5563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), 557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true, 558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true_label_, 559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch false_label_); 560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!lit->IsUndetectableObject()); // There are no undetectable literals. 5610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { 562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (false_label_ != fall_through_) __ b(false_label_); 5630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (lit->IsTrue() || lit->IsJSObject()) { 564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (true_label_ != fall_through_) __ b(true_label_); 5650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (lit->IsString()) { 5660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (String::cast(*lit)->length() == 0) { 5678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (false_label_ != fall_through_) __ b(false_label_); 5680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (true_label_ != fall_through_) __ b(true_label_); 5700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 5710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (lit->IsSmi()) { 5720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (Smi::cast(*lit)->value() == 0) { 573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (false_label_ != fall_through_) __ b(false_label_); 5740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (true_label_ != fall_through_) __ b(true_label_); 5760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 5770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 5780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // For simplicity we always test the accumulator register. 5790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(result_register(), Operand(lit)); 5803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch codegen()->DoTest(this); 581d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 582d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 583d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 584d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 5850d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::DropAndPlug(int count, 5860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(count > 0); 5880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Drop(count); 5890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 590e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 591e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 5920d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::DropAndPlug( 5930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int count, 5940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(count > 0); 5960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Drop(count); 5970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Move(result_register(), reg); 5980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 599e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 6000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6010d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::DropAndPlug(int count, 6020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(count > 0); 6040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (count > 1) __ Drop(count - 1); 6050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ str(reg, MemOperand(sp, 0)); 606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 607f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 608d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 6090d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::DropAndPlug(int count, 6100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(count > 0); 6120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // For simplicity we always test the accumulator register. 6130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Drop(count); 6140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Move(result_register(), reg); 6153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); 6163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch codegen()->DoTest(this); 6170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 619e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 6200d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Label* materialize_true, 6210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(materialize_true == materialize_false); 6230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_true); 6240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 625e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 6260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6270d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug( 6280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_true, 6290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 6300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label done; 6310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_true); 6320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), Heap::kTrueValueRootIndex); 6330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ jmp(&done); 6340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_false); 6350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), Heap::kFalseValueRootIndex); 6360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&done); 637d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 638d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 639d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 6400d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug( 6410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_true, 6420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 6430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label done; 6440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_true); 6450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(ip, Heap::kTrueValueRootIndex); 6460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ jmp(&done); 6470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_false); 6480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(ip, Heap::kFalseValueRootIndex); 6490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&done); 650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(ip); 6510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 6520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6540d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Label* materialize_true, 6550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(materialize_true == true_label_); 657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(materialize_false == false_label_); 6580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 6590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6610d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(bool flag) const { 6620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 6630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6650d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { 6660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex value_root_index = 6670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 6680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), value_root_index); 6690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 6700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6720d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(bool flag) const { 6730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex value_root_index = 6740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 6750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(ip, value_root_index); 6760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(ip); 6770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 6780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6800d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(bool flag) const { 6813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), 682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true, 683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true_label_, 684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch false_label_); 6850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (flag) { 6860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (true_label_ != fall_through_) __ b(true_label_); 6870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 6880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (false_label_ != fall_through_) __ b(false_label_); 689f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 690f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 691f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 692f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 6933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::DoTest(Expression* condition, 6943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label* if_true, 69580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false, 69680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through) { 697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); 698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, condition->test_id()); 699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ tst(result_register(), result_register()); 700e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Split(ne, if_true, if_false, fall_through); 70180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 702d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 703e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 7041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid FullCodeGenerator::Split(Condition cond, 70580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true, 70680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false, 70780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through) { 70880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (if_false == fall_through) { 7091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(cond, if_true); 71080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (if_true == fall_through) { 7111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(NegateCondition(cond), if_false); 71280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 7131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(cond, if_true); 71480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(if_false); 715d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 716d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 719589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::StackOperand(Variable* var) { 720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsStackAllocated()); 721589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Offset is negative because higher indexes are at lower addresses. 722589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int offset = -var->index() * kPointerSize; 723589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Adjust by a (parameter or local) base offset. 724589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsParameter()) { 725589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch offset += (info_->scope()->num_parameters() + 1) * kPointerSize; 726589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 727589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch offset += JavaScriptFrameConstants::kLocal0Offset; 728e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 729589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return MemOperand(fp, offset); 730e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 731e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 732e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 733589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) { 734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsContextSlot() || var->IsStackAllocated()); 735589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsContextSlot()) { 736589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int context_chain_length = scope()->ContextChainLength(var->scope()); 737589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ LoadContext(scratch, context_chain_length); 738589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return ContextOperand(scratch, var->index()); 739589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 740589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return StackOperand(var); 741589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 742589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch} 743589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 744589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 745589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::GetVar(Register dest, Variable* var) { 746e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Use destination as scratch. 747589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch MemOperand location = VarOperand(var, dest); 748589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ ldr(dest, location); 749e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 750e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 751e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 752589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::SetVar(Variable* var, 753589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register src, 754589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register scratch0, 755589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register scratch1) { 756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsContextSlot() || var->IsStackAllocated()); 757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch0.is(src)); 758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch0.is(scratch1)); 759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch1.is(src)); 760589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch MemOperand location = VarOperand(var, scratch0); 761e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(src, location); 7623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 763e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emit the write barrier code if the location is in the heap. 764589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsContextSlot()) { 7653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteContextSlot(scratch0, 7663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch location.offset(), 7673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch src, 7683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, 7693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kLRHasBeenSaved, 7703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs); 771e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 772d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 773d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 774d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 7753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr, 776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool should_normalize, 777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* if_true, 778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* if_false) { 779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Only prepare for bailouts before splits if we're in a test 780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // context. Otherwise, we let the Visit function deal with the 781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // preparation to avoid preparing with the same AST id twice. 782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!context()->IsTest() || !info_->IsOptimizable()) return; 783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label skip; 785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (should_normalize) __ b(&skip); 7863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailout(expr, TOS_REG); 787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (should_normalize) { 788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ LoadRoot(ip, Heap::kTrueValueRootIndex); 789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(r0, ip); 790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Split(eq, if_true, if_false, NULL); 791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&skip); 792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) { 797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The variable in the declaration always resides in the current function 798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // context. 799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0, scope()->ContextChainLength(variable->scope())); 800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (generate_debug_code_) { 801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that we're not inside a with or catch context. 802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r1, FieldMemOperand(cp, HeapObject::kMapOffset)); 803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(r1, Heap::kWithContextMapRootIndex); 804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(ne, kDeclarationInWithContext); 805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(r1, Heap::kCatchContextMapRootIndex); 806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(ne, kDeclarationInCatchContext); 807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitVariableDeclaration( 812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableDeclaration* declaration) { 813589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // If it was not possible to allocate the variable at compile time, we 814589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // need to "declare" it at runtime to make sure it actually exists in the 815589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // local context. 816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableProxy* proxy = declaration->proxy(); 817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableMode mode = declaration->mode(); 818589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* variable = proxy->var(); 819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY; 820589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch switch (variable->location()) { 821589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::UNALLOCATED: 822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch globals_->Add(variable->name(), zone()); 823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch globals_->Add(variable->binding_needs_init() 824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? isolate()->factory()->the_hole_value() 825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : isolate()->factory()->undefined_value(), 826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch zone()); 827589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 828589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 829589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::PARAMETER: 830589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOCAL: 831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hole_init) { 832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ VariableDeclaration"); 83369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 834589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ str(ip, StackOperand(variable)); 835d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 83669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch break; 837d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 838589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::CONTEXT: 839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hole_init) { 840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ VariableDeclaration"); 841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitDebugCheckDeclarationContext(variable); 84269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 843589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ str(ip, ContextOperand(cp, variable->index())); 84469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // No write barrier since the_hole_value is in old space. 845589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch PrepareForBailoutForId(proxy->id(), NO_REGISTERS); 84669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 84769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch break; 848257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 849589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOOKUP: { 850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ VariableDeclaration"); 85169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov(r2, Operand(variable->name())); 8523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Declaration nodes are always introduced in one of four modes. 853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsDeclaredVariableMode(mode)); 854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PropertyAttributes attr = 855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IsImmutableVariableMode(mode) ? READ_ONLY : NONE; 85669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov(r1, Operand(Smi::FromInt(attr))); 85769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Push initial value, if any. 85869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Note: For variables we must not push an initial value (such as 85969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // 'undefined') because we may have a (legal) redeclaration and we 86069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // must not destroy the current value. 861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hole_init) { 86269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); 86369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Push(cp, r2, r1, r0); 86469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else { 865589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ mov(r0, Operand(Smi::FromInt(0))); // Indicates no initial value. 86669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Push(cp, r2, r1, r0); 86769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kDeclareLookupSlot, 4); 869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitFunctionDeclaration( 876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FunctionDeclaration* declaration) { 877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableProxy* proxy = declaration->proxy(); 878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* variable = proxy->var(); 879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (variable->location()) { 880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::UNALLOCATED: { 881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch globals_->Add(variable->name(), zone()); 882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<SharedFunctionInfo> function = 883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Compiler::BuildFunctionInfo(declaration->fun(), script(), info_); 884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for stack-overflow exception. 885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (function.is_null()) return SetStackOverflow(); 886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch globals_->Add(function, zone()); 887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::PARAMETER: 891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::LOCAL: { 892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ FunctionDeclaration"); 893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(declaration->fun()); 894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(result_register(), StackOperand(variable)); 895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::CONTEXT: { 899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ FunctionDeclaration"); 900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitDebugCheckDeclarationContext(variable); 901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(declaration->fun()); 902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(result_register(), ContextOperand(cp, variable->index())); 903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = Context::SlotOffset(variable->index()); 904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We know that we have written a function, which is not a smi. 905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteContextSlot(cp, 906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch offset, 907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result_register(), 908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch r2, 909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kLRHasBeenSaved, 910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kDontSaveFPRegs, 911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EMIT_REMEMBERED_SET, 912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OMIT_SMI_CHECK); 913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(proxy->id(), NO_REGISTERS); 914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::LOOKUP: { 918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ FunctionDeclaration"); 919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r2, Operand(variable->name())); 920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r1, Operand(Smi::FromInt(NONE))); 921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(cp, r2, r1); 922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push initial value for function declaration. 923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(declaration->fun()); 924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kDeclareLookupSlot, 4); 925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { 932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* variable = declaration->proxy()->var(); 933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(variable->location() == Variable::CONTEXT); 934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(variable->interface()->IsFrozen()); 935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ ModuleDeclaration"); 937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitDebugCheckDeclarationContext(variable); 938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load instance object. 940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadContext(r1, scope_->ContextChainLength(scope_->GlobalScope())); 941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r1, ContextOperand(r1, variable->interface()->Index())); 942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r1, ContextOperand(r1, Context::EXTENSION_INDEX)); 943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Assign it. 945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r1, ContextOperand(cp, variable->index())); 946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We know that we have written a module, which is not a smi. 947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteContextSlot(cp, 948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Context::SlotOffset(variable->index()), 949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch r1, 950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch r3, 951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kLRHasBeenSaved, 952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kDontSaveFPRegs, 953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EMIT_REMEMBERED_SET, 954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OMIT_SMI_CHECK); 955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(declaration->proxy()->id(), NO_REGISTERS); 956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Traverse into body. 958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Visit(declaration->module()); 959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) { 963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableProxy* proxy = declaration->proxy(); 964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* variable = proxy->var(); 965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (variable->location()) { 966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::UNALLOCATED: 967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(rossberg) 968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::CONTEXT: { 971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ ImportDeclaration"); 972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitDebugCheckDeclarationContext(variable); 973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(rossberg) 97469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch break; 975d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::PARAMETER: 978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::LOCAL: 979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::LOOKUP: 980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 9813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 9823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 9833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) { 986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(rossberg) 987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 990d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 9913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Call the runtime to declare the globals. 9923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // The context is the first argument. 993589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ mov(r1, Operand(pairs)); 994589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ mov(r0, Operand(Smi::FromInt(DeclareGlobalsFlags()))); 995589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Push(cp, r1, r0); 996589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CallRuntime(Runtime::kDeclareGlobals, 3); 9973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Return value is ignored. 9983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 9993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { 1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the runtime to declare the modules. 1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(descriptions); 1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kDeclareModules, 1); 1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return value is ignored. 1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 1010f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ SwitchStatement"); 1011f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Breakable nested_statement(this, stmt); 1012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetStatementPosition(stmt); 1013e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Keep the switch value on the stack until a case matches. 10150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(stmt->tag()); 1016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); 1017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1018f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<CaseClause*>* clauses = stmt->cases(); 1019f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* default_clause = NULL; // Can occur anywhere in the list. 1020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1021f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label next_test; // Recycled for each test. 1022f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile all the tests with branches to their bodies. 1023f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < clauses->length(); i++) { 1024f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* clause = clauses->at(i); 10258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch clause->body_target()->Unuse(); 10261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1027f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The default is not a test, but remember it as final fall through. 1028f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (clause->is_default()) { 1029f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke default_clause = clause; 1030f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke continue; 1031f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1032f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1033f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ Case comparison"); 1034f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&next_test); 1035f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke next_test.Unuse(); 1036f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1037f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile the label expression. 10380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(clause->label()); 1039f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 104080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Perform the comparison as if via '==='. 1041f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(sp, 0)); // Switch value. 10420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT); 10431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block JumpPatchSite patch_site(masm_); 10440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (inline_smi_code) { 104580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label slow_case; 104680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ orr(r2, r1, r0); 10471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block patch_site.EmitJumpIfNotSmi(r2, &slow_case); 10481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 104980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r1, r0); 105080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ b(ne, &next_test); 105180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Drop(1); // Switch value is no longer needed. 10528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ b(clause->body_target()); 10531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&slow_case); 105480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 105580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 10561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Record position before stub call for type feedback. 10571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block SetSourcePosition(clause->position()); 1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = 1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code(); 1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, clause->CompareId()); 10613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 1062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label skip; 1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(&skip); 1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailout(clause, TOS_REG); 1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(ip, Heap::kTrueValueRootIndex); 1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r0, ip); 1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, &next_test); 1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Drop(1); 1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(clause->body_target()); 1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&skip); 1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r0, Operand::Zero()); 1074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &next_test); 1075f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(1); // Switch value is no longer needed. 10768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ b(clause->body_target()); 1077f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1078f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Discard the test value and jump to the default if present, otherwise to 1080f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // the end of the statement. 1081f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&next_test); 1082f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(1); // Switch value is no longer needed. 1083f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (default_clause == NULL) { 108469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ b(nested_statement.break_label()); 1085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 10868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ b(default_clause->body_target()); 1087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile all the case bodies. 1090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < clauses->length(); i++) { 1091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ Case body"); 1092f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* clause = clauses->at(i); 10938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ bind(clause->body_target()); 109444f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS); 1095f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitStatements(clause->statements()); 1096f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1097f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 109869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(nested_statement.break_label()); 1099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 1100f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1102f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1103f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { 1104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ ForInStatement"); 1105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int slot = stmt->ForInFeedbackSlot(); 1106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetStatementPosition(stmt); 1107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1108f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label loop, exit; 1109f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ForIn loop_statement(this, stmt); 1110f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke increment_loop_depth(); 1111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the object to enumerate over. If the object is null or undefined, skip 1113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // over the loop. See ECMA-262 version 5, section 12.6.4. 11140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(stmt->enumerable()); 1115f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 1116f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r0, ip); 1117f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, &exit); 1118e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register null_value = r5; 1119e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ LoadRoot(null_value, Heap::kNullValueRootIndex); 1120e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmp(r0, null_value); 1121f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, &exit); 1122f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 11233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutForId(stmt->PrepareId(), TOS_REG); 11243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1125f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Convert the object to a JS object. 1126f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label convert, done_convert; 11271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r0, &convert); 11283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE); 11293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ b(ge, &done_convert); 1130f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&convert); 1131f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); 1132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 1133f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done_convert); 1134f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); 1135f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 11363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for proxies. 11373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label call_runtime; 11383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 11393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareObjectType(r0, r1, r1, LAST_JS_PROXY_TYPE); 11403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(le, &call_runtime); 11413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1142e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Check cache validity in generated code. This is a fast case for 1143e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // the JSObject::IsSimpleEnum cache validity checks. If we cannot 1144e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // guarantee cache validity, call the runtime system to check cache 1145e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // validity or get the property names in a fixed array. 11463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckEnumCache(null_value, &call_runtime); 1147e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The enum cache is valid. Load the map of the object being 1149e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // iterated over and use the cache for the iteration. 1150e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Label use_cache; 1151e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); 1152e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(&use_cache); 1153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the set of properties to enumerate. 1155e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&call_runtime); 1156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); // Duplicate the enumerable object on the stack. 1157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); 1158f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If we got a map from the runtime call, we can do a fast 1160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // modification check. Otherwise, we got a fixed array, and we have 1161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // to do a slow check. 1162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label fixed_array; 1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); 1164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kMetaMapRootIndex); 1165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r2, ip); 1166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &fixed_array); 1167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // We got a map in register r0. Get the enumeration cache from it. 1169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label no_descriptors; 1170e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&use_cache); 1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ EnumLength(r1, r0); 1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r1, Operand(Smi::FromInt(0))); 1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(eq, &no_descriptors); 1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadInstanceDescriptors(r0, r2); 1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r2, FieldMemOperand(r2, DescriptorArray::kEnumCacheOffset)); 1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r2, FieldMemOperand(r2, DescriptorArray::kEnumCacheBridgeCacheOffset)); 1179f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 11803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the four remaining stack slots. 1181f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); // Map. 1182f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(Smi::FromInt(0))); 1183f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Push enumeration cache, enumeration cache length (as smi) and zero. 1184f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(r2, r1, r0); 1185f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&loop); 1186f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&no_descriptors); 1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Drop(1); 1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&exit); 1190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1191f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // We got a fixed array in register r0. Iterate through that. 11923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label non_proxy; 1193f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&fixed_array); 11943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(r1, FeedbackVector()); 1196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r2, Operand(TypeFeedbackVector::MegamorphicSentinel(isolate()))); 1197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r2, FieldMemOperand(r1, FixedArray::OffsetOfElementAt(slot))); 11983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 11993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r1, Operand(Smi::FromInt(1))); // Smi indicates slow check 12003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r2, MemOperand(sp, 0 * kPointerSize)); // Get enumerated object 12013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 12023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareObjectType(r2, r3, r3, LAST_JS_PROXY_TYPE); 12033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(gt, &non_proxy); 12043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r1, Operand(Smi::FromInt(0))); // Zero indicates proxy 12053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&non_proxy); 12063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(r1, r0); // Smi and array 1207f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset)); 1208f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(Smi::FromInt(0))); 1209f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(r1, r0); // Fixed array length (as smi) and initial index. 1210f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1211f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for doing the condition check. 12123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); 1213f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&loop); 1214f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the current count to r0, load the length to r1. 1215f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize)); 1216f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r0, r1); // Compare to the array length. 121769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ b(hs, loop_statement.break_label()); 1218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the current entry of the array into register r3. 1220f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(sp, 2 * kPointerSize)); 1221f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r3, MemOperand::PointerAddressFromSmiKey(r2, r0)); 1223f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 12243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the expected map from the stack or a smi in the 1225f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // permanent slow case into register r2. 1226f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(sp, 3 * kPointerSize)); 1227f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1228f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the expected map still matches that of the enumerable. 12293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If not, we may have to filter the key. 1230f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label update_each; 1231f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(sp, 4 * kPointerSize)); 1232f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r4, FieldMemOperand(r1, HeapObject::kMapOffset)); 1233f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r4, Operand(r2)); 1234f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, &update_each); 1235f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 12363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // For proxies, no filtering is done. 12373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // TODO(rossberg): What if only a prototype is a proxy? Not specified yet. 12383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r2, Operand(Smi::FromInt(0))); 12393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(eq, &update_each); 12403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1241756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Convert the entry to a string or (smi) 0 if it isn't a property 1242756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // any more. If the property has been removed while iterating, we 1243f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // just skip it. 1244f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r1); // Enumerable. 1245f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r3); // Current entry. 1246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); 1247756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ mov(r3, Operand(r0), SetCC); 124869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ b(eq, loop_statement.continue_label()); 1249f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1250f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Update the 'each' property or variable from the possibly filtered 1251f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // entry in register r3. 1252f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&update_each); 1253f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(result_register(), r3); 1254f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment as if via '='. 1255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { EffectContext context(this); 12563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitAssignment(stmt->each()); 1257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1258f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1259f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for the body of the loop. 1260f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Visit(stmt->body()); 1261f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1262f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for the going to the next element by incrementing 1263f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // the index (smi) stored on top of the stack. 126469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(loop_statement.continue_label()); 1265f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r0); 1266f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ add(r0, r0, Operand(Smi::FromInt(1))); 1267f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); 1268f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBackEdgeBookkeeping(stmt, &loop); 1270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ b(&loop); 1271f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1272f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Remove the pointers stored on the stack. 127369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(loop_statement.break_label()); 1274f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(5); 1275f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1276f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Exit and decrement the loop depth. 12773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 1278f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&exit); 1279f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke decrement_loop_depth(); 1280f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 12813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { 1284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ ForOfStatement"); 1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetStatementPosition(stmt); 1286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Iteration loop_statement(this, stmt); 1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch increment_loop_depth(); 1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // var iterator = iterable[Symbol.iterator](); 1291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForEffect(stmt->assign_iterator()); 1292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Loop entry. 1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(loop_statement.continue_label()); 1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // result = iterator.next() 1297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForEffect(stmt->next_result()); 1298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // if (result.done) break; 1300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label result_not_done; 1301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForControl(stmt->result_done(), 1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch loop_statement.break_label(), 1303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &result_not_done, 1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &result_not_done); 1305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&result_not_done); 1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // each = result.value 1308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForEffect(stmt->assign_each()); 1309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generate code for the body of the loop. 1311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Visit(stmt->body()); 1312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check stack before looping. 1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS); 1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label()); 1316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(loop_statement.continue_label()); 1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Exit and decrement the loop depth. 1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(loop_statement.break_label()); 1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch decrement_loop_depth(); 1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 13258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, 13268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang bool pretenure) { 1327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Use the fast case closure allocation code that allocates in new 1328e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // space for nested functions that don't need literals cloning. If 1329e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // we're running with the --always-opt or the --prepare-always-opt 1330e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // flag, we need to use the runtime function so that the new function 1331e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // we are creating here gets a chance to have its code optimized and 1332e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // doesn't just get a copy of the existing unoptimized code. 1333e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!FLAG_always_opt && 1334e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch !FLAG_prepare_always_opt && 133544f0eee88ff00398ff7f715fab053374d808c90dSteve Block !pretenure && 1336e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch scope()->is_function_scope() && 133744f0eee88ff00398ff7f715fab053374d808c90dSteve Block info->num_literals() == 0) { 1338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind()); 1339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r2, Operand(info)); 1340f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 1341f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1342f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r0, Operand(info)); 13438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ LoadRoot(r1, pretenure ? Heap::kTrueValueRootIndex 13448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang : Heap::kFalseValueRootIndex); 13458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Push(cp, r0, r1); 13468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ CallRuntime(Runtime::kNewClosure, 3); 1347f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 13480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 13493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 13503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1352d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 13533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ VariableProxy"); 13543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch EmitVariableLoad(expr); 1355e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1356e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1357e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) { 1359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cnmt(masm_, "[ SuperReference "); 1360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(LoadDescriptor::ReceiverRegister(), 1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 1363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol()); 1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(LoadDescriptor::NameRegister(), home_object_symbol); 1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId()); 1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r0, Operand(isolate()->factory()->undefined_value())); 1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 1371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, &done); 1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kThrowNonMethodError, 0); 1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, 1378589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch TypeofState typeof_state, 1379589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label* slow) { 1380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register current = cp; 1381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register next = r1; 1382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register temp = r2; 1383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Scope* s = scope(); 1385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch while (s != NULL) { 1386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (s->num_heap_slots() > 0) { 1387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (s->calls_sloppy_eval()) { 1388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that extension is NULL. 1389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldr(temp, ContextOperand(current, Context::EXTENSION_INDEX)); 1390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ tst(temp, temp); 1391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ b(ne, slow); 1392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load next context in chain. 13943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ldr(next, ContextOperand(current, Context::PREVIOUS_INDEX)); 1395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Walk the rest of the chain without clobbering cp. 1396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch current = next; 1397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If no outer scope calls eval, we do not need to check more 1399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // context extensions. 1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!s->outer_scope_calls_sloppy_eval() || s->is_eval_scope()) break; 1401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch s = s->outer_scope(); 1402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (s->is_eval_scope()) { 1405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label loop, fast; 1406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!current.is(next)) { 1407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Move(next, current); 1408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&loop); 1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Terminate at native context. 1411257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldr(temp, FieldMemOperand(next, HeapObject::kMapOffset)); 1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(ip, Heap::kNativeContextMapRootIndex); 1413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(temp, ip); 1414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ b(eq, &fast); 1415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that extension is NULL. 1416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldr(temp, ContextOperand(next, Context::EXTENSION_INDEX)); 1417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ tst(temp, temp); 1418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ b(ne, slow); 1419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load next context in chain. 14203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ldr(next, ContextOperand(next, Context::PREVIOUS_INDEX)); 1421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ b(&loop); 1422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&fast); 1423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1424257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); 1426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(LoadDescriptor::NameRegister(), Operand(proxy->var()->name())); 1427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 1428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(VectorLoadICDescriptor::SlotRegister(), 1429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(Smi::FromInt(proxy->VariableFeedbackSlot()))); 1430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ContextualMode mode = (typeof_state == INSIDE_TYPEOF) 1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? NOT_CONTEXTUAL 1434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : CONTEXTUAL; 1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(mode); 1436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1439589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, 1440589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label* slow) { 1441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsContextSlot()); 1442e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register context = cp; 144359151504615d929945dc59db37bf1166937748c6Steve Block Register next = r3; 144459151504615d929945dc59db37bf1166937748c6Steve Block Register temp = r4; 144559151504615d929945dc59db37bf1166937748c6Steve Block 1446589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { 144759151504615d929945dc59db37bf1166937748c6Steve Block if (s->num_heap_slots() > 0) { 1448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (s->calls_sloppy_eval()) { 144959151504615d929945dc59db37bf1166937748c6Steve Block // Check that extension is NULL. 1450e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(temp, ContextOperand(context, Context::EXTENSION_INDEX)); 145159151504615d929945dc59db37bf1166937748c6Steve Block __ tst(temp, temp); 145259151504615d929945dc59db37bf1166937748c6Steve Block __ b(ne, slow); 145359151504615d929945dc59db37bf1166937748c6Steve Block } 14543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ldr(next, ContextOperand(context, Context::PREVIOUS_INDEX)); 145559151504615d929945dc59db37bf1166937748c6Steve Block // Walk the rest of the chain without clobbering cp. 1456e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch context = next; 145759151504615d929945dc59db37bf1166937748c6Steve Block } 145859151504615d929945dc59db37bf1166937748c6Steve Block } 145959151504615d929945dc59db37bf1166937748c6Steve Block // Check that last extension is NULL. 1460e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(temp, ContextOperand(context, Context::EXTENSION_INDEX)); 146159151504615d929945dc59db37bf1166937748c6Steve Block __ tst(temp, temp); 146259151504615d929945dc59db37bf1166937748c6Steve Block __ b(ne, slow); 1463e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1464e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // This function is used only for loads, not stores, so it's safe to 1465e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // return an cp-based operand (the write barrier cannot be allowed to 1466e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // destroy the cp register). 1467589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return ContextOperand(context, var->index()); 146859151504615d929945dc59db37bf1166937748c6Steve Block} 146959151504615d929945dc59db37bf1166937748c6Steve Block 147059151504615d929945dc59db37bf1166937748c6Steve Block 1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy, 1472589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch TypeofState typeof_state, 1473589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label* slow, 1474589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label* done) { 147559151504615d929945dc59db37bf1166937748c6Steve Block // Generate fast-case code for variables that might be shadowed by 147659151504615d929945dc59db37bf1166937748c6Steve Block // eval-introduced variables. Eval is used a lot without 147759151504615d929945dc59db37bf1166937748c6Steve Block // introducing variables. In those cases, we do not want to 147859151504615d929945dc59db37bf1166937748c6Steve Block // perform a runtime call for all variables in the scope 147959151504615d929945dc59db37bf1166937748c6Steve Block // containing the eval. 1480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* var = proxy->var(); 14813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (var->mode() == DYNAMIC_GLOBAL) { 1482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitLoadGlobalCheckExtensions(proxy, typeof_state, slow); 148359151504615d929945dc59db37bf1166937748c6Steve Block __ jmp(done); 14843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (var->mode() == DYNAMIC_LOCAL) { 1485589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* local = var->local_if_not_shadowed(); 1486589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ ldr(r0, ContextSlotOperandCheckExtensions(local, slow)); 1487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (local->mode() == LET || local->mode() == CONST || 1488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch local->mode() == CONST_LEGACY) { 1489589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); 1490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (local->mode() == CONST_LEGACY) { 14913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); 1492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { // LET || CONST 14933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, done); 14943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r0, Operand(var->name())); 14953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 14963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kThrowReferenceError, 1); 14973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 149859151504615d929945dc59db37bf1166937748c6Steve Block } 1499589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ jmp(done); 150059151504615d929945dc59db37bf1166937748c6Steve Block } 150159151504615d929945dc59db37bf1166937748c6Steve Block} 150259151504615d929945dc59db37bf1166937748c6Steve Block 150359151504615d929945dc59db37bf1166937748c6Steve Block 15043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { 15053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Record position before possible IC call. 15063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SetSourcePosition(proxy->position()); 15073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Variable* var = proxy->var(); 15083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1509589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Three cases: global variables, lookup variables, and all other types of 1510589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // variables. 1511589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch switch (var->location()) { 1512589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::UNALLOCATED: { 1513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Global variable"); 1514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); 1515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(LoadDescriptor::NameRegister(), Operand(var->name())); 1516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 1517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(VectorLoadICDescriptor::SlotRegister(), 1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(Smi::FromInt(proxy->VariableFeedbackSlot()))); 1519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(CONTEXTUAL); 1521589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch context()->Plug(r0); 1522589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 1523589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 152459151504615d929945dc59db37bf1166937748c6Steve Block 1525589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::PARAMETER: 1526589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOCAL: 1527589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::CONTEXT: { 1528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" 1529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : "[ Stack variable"); 15303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (var->binding_needs_init()) { 15313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // var->scope() may be NULL when the proxy is located in eval code and 15323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // refers to a potential outside binding. Currently those bindings are 15333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // always looked up dynamically, i.e. in that case 15343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // var->location() == LOOKUP. 15353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // always holds. 1536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->scope() != NULL); 15373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if the binding really needs an initialization check. The check 15393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // can be skipped in the following situation: we have a LET or CONST 15403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // binding in harmony mode, both the Variable and the VariableProxy have 15413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the same declaration scope (i.e. they are both in global code, in the 15423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // same function or in the same eval code) and the VariableProxy is in 15433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the source physically located after the initializer of the variable. 15443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 15453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We cannot skip any initialization checks for CONST in non-harmony 15463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // mode because const variables may be declared but never initialized: 15473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // if (false) { const x; }; var y = x; 15483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 15493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The condition on the declaration scopes is a conservative check for 15503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // nested functions that access a binding and are called before the 15513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // binding is initialized: 15523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // function() { f(); let x = 1; function f() { x = 2; } } 15533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 15543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool skip_init_check; 15553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) { 15563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch skip_init_check = false; 1557589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 15583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that we always have valid source position. 1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->initializer_position() != RelocInfo::kNoPosition); 1560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(proxy->position() != RelocInfo::kNoPosition); 1561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch skip_init_check = var->mode() != CONST_LEGACY && 15623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var->initializer_position() < proxy->position(); 15633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 15643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!skip_init_check) { 15663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Let and const need a read barrier. 15673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GetVar(r0, var); 15683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); 1569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->mode() == LET || var->mode() == CONST) { 15703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Throw a reference error when using an uninitialized let/const 15713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // binding in harmony mode. 15723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label done; 15733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &done); 15743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r0, Operand(var->name())); 15753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kThrowReferenceError, 1); 15773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 15783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 15793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Uninitalized const bindings outside of harmony mode are unholed. 1580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->mode() == CONST_LEGACY); 15813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); 15823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 15833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(r0); 15843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 1585589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 1586589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 15873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(var); 1588589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 1589589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 1590d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1591589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOOKUP: { 1592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Lookup variable"); 1593589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label done, slow; 1594589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Generate code for loading from variables potentially shadowed 1595589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // by eval-introduced variables. 1596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done); 1597589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ bind(&slow); 1598589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ mov(r1, Operand(var->name())); 1599589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Push(cp, r1); // Context and name. 1600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kLoadLookupSlot, 2); 160169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(&done); 160269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch context()->Plug(r0); 16030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 16043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 16053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 16063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1608d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 1609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ RegExpLiteral"); 1610bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Label materialized; 16113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Registers will be used as follows: 1612e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // r5 = materialized value (RegExp literal) 16133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // r4 = JS function, literals array 16143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // r3 = literal index 16153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // r2 = RegExp pattern 16163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // r1 = RegExp flags 1617e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // r0 = RegExp literal clone 161880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 161980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); 16203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int literal_offset = 162180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; 1622e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(r5, FieldMemOperand(r4, literal_offset)); 16233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 1624e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmp(r5, ip); 1625bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ b(ne, &materialized); 162680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 162780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Create regexp literal using runtime function. 162880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Result will be in r0. 16293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(r3, Operand(Smi::FromInt(expr->literal_index()))); 16303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(r2, Operand(expr->pattern())); 16313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(r1, Operand(expr->flags())); 16326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Push(r4, r3, r2, r1); 16333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 1634e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(r5, r0); 163580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1636bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&materialized); 1637bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; 1638e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Label allocated, runtime_allocate; 1639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Allocate(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT); 1640e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ jmp(&allocated); 1641e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1642e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&runtime_allocate); 1643bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ mov(r0, Operand(Smi::FromInt(size))); 1644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(r5, r0); 1645bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ CallRuntime(Runtime::kAllocateInNewSpace, 1); 1646e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ pop(r5); 164780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1648e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&allocated); 1649bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // After this, registers are used as follows: 1650bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // r0: Newly allocated regexp. 1651e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // r5: Materialized regexp. 1652bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // r2: temp. 1653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CopyFields(r0, r5, d0, size / kPointerSize); 16540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 1655d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1656d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1657d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 16583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitAccessor(Expression* expression) { 16593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (expression == NULL) { 16603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r1, Heap::kNullValueRootIndex); 16613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r1); 16623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 16633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForStackValue(expression); 16643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 16653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 16663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 16673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1668d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 1669d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ ObjectLiteral"); 1670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch expr->BuildConstantProperties(isolate()); 16723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedArray> constant_properties = expr->constant_properties(); 1673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 16746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); 16756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); 16763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r1, Operand(constant_properties)); 167744f0eee88ff00398ff7f715fab053374d808c90dSteve Block int flags = expr->fast_elements() 167844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ? ObjectLiteral::kFastElements 167944f0eee88ff00398ff7f715fab053374d808c90dSteve Block : ObjectLiteral::kNoFlags; 168044f0eee88ff00398ff7f715fab053374d808c90dSteve Block flags |= expr->has_function() 168144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ? ObjectLiteral::kHasFunction 168244f0eee88ff00398ff7f715fab053374d808c90dSteve Block : ObjectLiteral::kNoFlags; 168344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(r0, Operand(Smi::FromInt(flags))); 16843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int properties_count = constant_properties->length() / 2; 1685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->may_store_doubles() || expr->depth() > 1 || 1686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm()->serializer_enabled() || flags != ObjectLiteral::kFastElements || 16873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { 1688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(r3, r2, r1, r0); 1689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kCreateObjectLiteral, 4); 16903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FastCloneShallowObjectStub stub(isolate(), properties_count); 16923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallStub(&stub); 1693d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1694d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1695e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // If result_saved is true the result is on top of the stack. If 1696e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // result_saved is false the result is in r0. 1697d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool result_saved = false; 1698d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 16993e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Mark all computed expressions that are bound to a key that 17003e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // is shadowed by a later occurrence of the same key. For the 17013e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // marked expressions, no store code is emitted. 1702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch expr->CalculateEmitStore(zone()); 17033e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 1704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AccessorTable accessor_table(zone()); 1705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < expr->properties()->length(); i++) { 1706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ObjectLiteral::Property* property = expr->properties()->at(i); 1707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (property->IsCompileTimeValue()) continue; 1708d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1709d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key = property->key(); 1710d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* value = property->value(); 1711d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (!result_saved) { 1712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r0); // Save result on stack 1713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result_saved = true; 1714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1715d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (property->kind()) { 1716d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::CONSTANT: 1717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 1718e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); 1720e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 1721d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::COMPUTED: 1722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (key->value()->IsInternalizedString()) { 17233e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu if (property->emit_store()) { 1724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForAccumulatorValue(value); 1725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(StoreDescriptor::ValueRegister().is(r0)); 1726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(StoreDescriptor::NameRegister(), Operand(key->value())); 1727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); 1728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallStoreIC(key->LiteralFeedbackId()); 1729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(key->id(), NO_REGISTERS); 1730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForEffect(value); 17323e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 1733d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1734d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1735e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Duplicate receiver on stack. 1736e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldr(r0, MemOperand(sp)); 1737d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r0); 17380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(key); 17390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(value); 17403e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu if (property->emit_store()) { 1741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r0, Operand(Smi::FromInt(SLOPPY))); // PropertyAttributes 1742e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(r0); 1743e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CallRuntime(Runtime::kSetProperty, 4); 17443e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } else { 17453e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ Drop(3); 17463e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 1747d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case ObjectLiteral::Property::PROTOTYPE: 1749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Duplicate receiver on stack. 1750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r0, MemOperand(sp)); 1751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r0); 1752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(value); 1753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (property->emit_store()) { 1754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kSetPrototype, 2); 1755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Drop(2); 1757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1760e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::GETTER: 17613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch accessor_table.lookup(key)->second->getter = value; 17623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 1763d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::SETTER: 17643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch accessor_table.lookup(key)->second->setter = value; 1765d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1766d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1768e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 17693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Emit code to define accessors, using only a single call to the runtime for 17703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // each pair of corresponding getters and setters. 17713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (AccessorTable::Iterator it = accessor_table.begin(); 17723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch it != accessor_table.end(); 17733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ++it) { 17743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, MemOperand(sp)); // Duplicate receiver. 17753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 17763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForStackValue(it->first); 17773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitAccessor(it->second->getter); 17783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitAccessor(it->second->setter); 17793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r0, Operand(Smi::FromInt(NONE))); 17803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 1781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); 17823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 17833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 178444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (expr->has_function()) { 1785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(result_saved); 178644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ ldr(r0, MemOperand(sp)); 178744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ push(r0); 178844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CallRuntime(Runtime::kToFastProperties, 1); 178944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 179044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1791e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 17920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 1793e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 17940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 17953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 17963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 17973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 17983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1799d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 18003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ ArrayLiteral"); 1801f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch expr->BuildConstantElements(isolate()); 1803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int flags = expr->depth() == 1 1804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? ArrayLiteral::kShallowElements 1805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : ArrayLiteral::kNoFlags; 1806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<Expression*>* subexprs = expr->values(); 1808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int length = subexprs->length(); 18093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedArray> constant_elements = expr->constant_elements(); 1810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(2, constant_elements->length()); 18113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind constant_elements_kind = 18123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); 1813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool has_fast_elements = IsFastObjectElementsKind(constant_elements_kind); 18143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedArrayBase> constant_elements_values( 18153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArrayBase::cast(constant_elements->get(1))); 1816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE; 1818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (has_fast_elements && !FLAG_allocation_site_pretenuring) { 1819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the only customer of allocation sites is transitioning, then 1820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // we can turn it off if we don't have anywhere else to transition to. 1821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; 1822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 18243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 18253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); 18263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); 18273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r1, Operand(constant_elements)); 1828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) { 1829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r0, Operand(Smi::FromInt(flags))); 1830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(r3, r2, r1, r0); 1831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kCreateArrayLiteral, 4); 1832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); 1834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 18353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 18363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 18373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bool result_saved = false; // Is the result saved to the stack? 18383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 18393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Emit code to evaluate all the non-constant subexpressions and to store 18403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // them into the newly cloned array. 1841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < length; i++) { 18423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Expression* subexpr = subexprs->at(i); 18433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If the subexpression is a literal or a simple materialized literal it 18443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // is already set in the cloned array. 1845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; 18463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 18473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!result_saved) { 18483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(r0); 1849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Smi::FromInt(expr->literal_index())); 18503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block result_saved = true; 18513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 18520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(subexpr); 18533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsFastObjectElementsKind(constant_elements_kind)) { 18553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int offset = FixedArray::kHeaderSize + (i * kPointerSize); 1856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r6, MemOperand(sp, kPointerSize)); // Copy of array literal. 18573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r1, FieldMemOperand(r6, JSObject::kElementsOffset)); 18583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(result_register(), FieldMemOperand(r1, offset)); 18593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Update the write barrier for the array store. 18603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(r1, offset, result_register(), r2, 18613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kLRHasBeenSaved, kDontSaveFPRegs, 18623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, INLINE_SMI_CHECK); 18633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 18643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r3, Operand(Smi::FromInt(i))); 1865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StoreArrayLiteralElementStub stub(isolate()); 18663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallStub(&stub); 18673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); 18703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 18713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1872e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 1873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(); // literal index 18740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 1875e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 18760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 18773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 18783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 18793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 18803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1881402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) { 1882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->target()->IsValidReferenceExpression()); 1883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1884402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Comment cmnt(masm_, "[ Assignment"); 1885f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1886402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Left-hand side can only be a property, a global or a (parameter or local) 18873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // slot. 1888402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1889402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu LhsKind assign_type = VARIABLE; 189080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Property* property = expr->target()->AsProperty(); 189180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (property != NULL) { 189280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen assign_type = (property->key()->IsPropertyName()) 189380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ? NAMED_PROPERTY 189480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen : KEYED_PROPERTY; 1895402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1896402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1897402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Evaluate LHS expression. 1898402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1899402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1900402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Nothing to do here. 1901402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1902402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1903402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 1904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We need the receiver both on the stack and in the register. 1905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(property->obj()); 1906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0)); 1907402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 19080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(property->obj()); 1909402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1910402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1911402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 191225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (expr->is_compound()) { 19133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(property->obj()); 1914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(property->key()); 1915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(LoadDescriptor::ReceiverRegister(), 1916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand(sp, 1 * kPointerSize)); 1917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(LoadDescriptor::NameRegister(), MemOperand(sp, 0)); 191825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 19193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(property->obj()); 19203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(property->key()); 192125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 1922402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1923402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1924402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 19258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // For compound assignments we need another deoptimization point after the 19268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // variable/property load. 1927402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 19280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { AccumulatorValueContext context(this); 19290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen switch (assign_type) { 19300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case VARIABLE: 19313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch EmitVariableLoad(expr->target()->AsVariableProxy()); 19328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PrepareForBailout(expr->target(), TOS_REG); 19330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 19340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case NAMED_PROPERTY: 19350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitNamedPropertyLoad(property); 1936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(property->LoadId(), TOS_REG); 19370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 19380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case KEYED_PROPERTY: 19390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitKeyedPropertyLoad(property); 1940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(property->LoadId(), TOS_REG); 19410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 19420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 1943402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1944402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 194580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Token::Value op = expr->binary_op(); 1946e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(r0); // Left operand goes on the stack. 1947e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitForAccumulatorValue(expr->value()); 1948402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 194980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen OverwriteMode mode = expr->value()->ResultOverwriteAllowed() 195080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ? OVERWRITE_RIGHT 195180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen : NO_OVERWRITE; 195280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen SetSourcePosition(expr->position() + 1); 19530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AccumulatorValueContext context(this); 195480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (ShouldInlineSmiCase(op)) { 1955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitInlineSmiBinaryOp(expr->binary_operation(), 195680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen op, 195780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen mode, 195880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen expr->target(), 1959e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch expr->value()); 196080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 1961257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitBinaryOp(expr->binary_operation(), op, mode); 196280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 1963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Deoptimization point in case the binary operation may have side effects. 1965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailout(expr->binary_operation(), TOS_REG); 196680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 19670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->value()); 1968402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1969402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1970402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Record source position before possible IC call. 1971402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu SetSourcePosition(expr->position()); 1972402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1973402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Store the value. 1974402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1975402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1976402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), 19770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen expr->op()); 1978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 1979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(r0); 1980402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1981402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1982402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitNamedPropertyAssignment(expr); 1983402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1984402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 1985402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitKeyedPropertyAssignment(expr); 1986402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1987402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1988402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 1989402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1990402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitYield(Yield* expr) { 1992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Yield"); 1993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Evaluate yielded value first; the initial iterator definition depends on 1994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // this. It stays on the stack while we update the iterator. 1995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(expr->expression()); 1996e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (expr->yield_kind()) { 1998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Yield::kSuspend: 1999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pop value from top-of-stack slot; box result into result register. 2000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCreateIteratorResult(false); 2001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(result_register()); 2002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Fall through. 2003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Yield::kInitial: { 2004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label suspend, continuation, post_runtime, resume; 2005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&suspend); 2007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&continuation); 2009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&resume); 2010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&suspend); 2012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(expr->generator_object()); 2013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); 2014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r1, Operand(Smi::FromInt(continuation.pos()))); 2015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r1, FieldMemOperand(r0, JSGeneratorObject::kContinuationOffset)); 2016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(cp, FieldMemOperand(r0, JSGeneratorObject::kContextOffset)); 2017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r1, cp); 2018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteField(r0, JSGeneratorObject::kContextOffset, r1, r2, 2019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kLRHasBeenSaved, kDontSaveFPRegs); 2020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(r1, fp, Operand(StandardFrameConstants::kExpressionsOffset)); 2021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(sp, r1); 2022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(eq, &post_runtime); 2023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r0); // generator object 2024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); 2025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&post_runtime); 2027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(result_register()); 2028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitReturnSequence(); 2029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&resume); 2031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(result_register()); 2032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2034e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Yield::kFinal: { 2036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(expr->generator_object()); 2037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r1, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorClosed))); 2038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r1, FieldMemOperand(result_register(), 2039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSGeneratorObject::kContinuationOffset)); 2040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pop value from top-of-stack slot, box result into result register. 2041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCreateIteratorResult(true); 2042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitUnwindBeforeReturn(); 2043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitReturnSequence(); 2044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2046e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Yield::kDelegating: { 2048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(expr->generator_object()); 2049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Initial stack layout is as follows: 2051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // [sp + 1 * kPointerSize] iter 2052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // [sp + 0 * kPointerSize] g 2053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label l_catch, l_try, l_suspend, l_continuation, l_resume; 2055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label l_next, l_call, l_loop; 2056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register load_receiver = LoadDescriptor::ReceiverRegister(); 2057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register load_name = LoadDescriptor::NameRegister(); 2058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Initial send value is undefined. 2060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 2061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(&l_next); 2062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } 2064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&l_catch); 2065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); 2066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(load_name, Heap::kthrow_stringRootIndex); // "throw" 2067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter 2068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(load_name, r3, r0); // "throw", iter, except 2069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&l_call); 2070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // try { received = %yield result } 2072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Shuffle the received result above a try handler and yield it without 2073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // re-boxing. 2074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&l_try); 2075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(r0); // result 2076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushTryHandler(StackHandler::CATCH, expr->index()); 2077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int handler_size = StackHandlerConstants::kSize; 2078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r0); // result 2079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&l_suspend); 2080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&l_continuation); 2081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&l_resume); 2082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&l_suspend); 2083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int generator_object_depth = kPointerSize + handler_size; 2084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r0, MemOperand(sp, generator_object_depth)); 2085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r0); // g 2086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); 2087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r1, Operand(Smi::FromInt(l_continuation.pos()))); 2088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r1, FieldMemOperand(r0, JSGeneratorObject::kContinuationOffset)); 2089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(cp, FieldMemOperand(r0, JSGeneratorObject::kContextOffset)); 2090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r1, cp); 2091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteField(r0, JSGeneratorObject::kContextOffset, r1, r2, 2092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kLRHasBeenSaved, kDontSaveFPRegs); 2093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); 2094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(r0); // result 2096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitReturnSequence(); 2097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&l_resume); // received in r0 2098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PopTryHandler(); 2099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // receiver = iter; f = 'next'; arg = received; 2101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&l_next); 2102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(load_name, Heap::knext_stringRootIndex); // "next" 2104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter 2105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(load_name, r3, r0); // "next", iter, received 2106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // result = receiver[f](arg); 2108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&l_call); 2109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(load_receiver, MemOperand(sp, kPointerSize)); 2110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(load_name, MemOperand(sp, 2 * kPointerSize)); 2111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 2112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(VectorLoadICDescriptor::SlotRegister(), 2113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(Smi::FromInt(expr->KeyedLoadFeedbackSlot()))); 2114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code(); 2116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, TypeFeedbackId::None()); 2117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r1, r0); 2118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r1, MemOperand(sp, 2 * kPointerSize)); 2119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD); 2120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallStub(&stub); 2121e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Drop(1); // The function is still on the stack; drop it. 2124e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // if (!result.done) goto l_try; 2126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&l_loop); 2127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(load_receiver, r0); 2128e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(load_receiver); // save result 2130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done" 2131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 2132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(VectorLoadICDescriptor::SlotRegister(), 2133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(Smi::FromInt(expr->DoneFeedbackSlot()))); 2134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(NOT_CONTEXTUAL); // r0=result.done 2136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); 2137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(bool_ic); 2138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r0, Operand(0)); 2139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(eq, &l_try); 2140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // result.value 2142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(load_receiver); // result 2143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value" 2144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 2145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(VectorLoadICDescriptor::SlotRegister(), 2146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(Smi::FromInt(expr->ValueFeedbackSlot()))); 2147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(NOT_CONTEXTUAL); // r0=result.value 2149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->DropAndPlug(2, r0); // drop iter and g 2150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2154e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2155e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitGeneratorResume(Expression *generator, 2157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression *value, 2158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSGeneratorObject::ResumeMode resume_mode) { 2159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The value stays in r0, and is ultimately read by the resumed generator, as 2160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it 2161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is read to throw the value when the resumed generator is already closed. 2162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r1 will hold the generator object until the activation has been resumed. 2163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(generator); 2164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(value); 2165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(r1); 2166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check generator state. 2168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label wrong_state, closed_state, done; 2169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r3, FieldMemOperand(r1, JSGeneratorObject::kContinuationOffset)); 2170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0); 2171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0); 2172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r3, Operand(Smi::FromInt(0))); 2173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(eq, &closed_state); 2174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(lt, &wrong_state); 2175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load suspended function and context. 2177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(cp, FieldMemOperand(r1, JSGeneratorObject::kContextOffset)); 2178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r4, FieldMemOperand(r1, JSGeneratorObject::kFunctionOffset)); 2179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load receiver and store as the first argument. 2181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r2, FieldMemOperand(r1, JSGeneratorObject::kReceiverOffset)); 2182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r2); 2183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push holes for the rest of the arguments to the generator function. 2185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r3, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); 2186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r3, 2187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset)); 2188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(r2, Heap::kTheHoleValueRootIndex); 2189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label push_argument_holes, push_frame; 2190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&push_argument_holes); 2191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(r3, r3, Operand(Smi::FromInt(1)), SetCC); 2192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(mi, &push_frame); 2193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r2); 2194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&push_argument_holes); 2195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Enter a new JavaScript frame, and initialize its slots as they were when 2197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the generator was suspended. 2198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label resume_frame; 2199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&push_frame); 2200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bl(&resume_frame); 2201e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ jmp(&done); 2202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&resume_frame); 2203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // lr = return address. 2204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // fp = caller's frame pointer. 2205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // pp = caller's constant pool (if FLAG_enable_ool_constant_pool), 2206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // cp = callee's context, 2207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r4 = callee's JS function. 2208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushFixedFrame(r4); 2209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Adjust FP to point to saved FP. 2210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); 2211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the operand stack size. 2213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r3, FieldMemOperand(r1, JSGeneratorObject::kOperandStackOffset)); 2214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r3, FieldMemOperand(r3, FixedArray::kLengthOffset)); 2215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(r3); 2216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we are sending a value and there is no operand stack, we can jump back 2218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // in directly. 2219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (resume_mode == JSGeneratorObject::NEXT) { 2220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow_resume; 2221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r3, Operand(0)); 2222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, &slow_resume); 2223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r3, FieldMemOperand(r4, JSFunction::kCodeEntryOffset)); 2224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { ConstantPoolUnavailableScope constant_pool_unavailable(masm_); 2226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_enable_ool_constant_pool) { 2227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the new code object's constant pool pointer. 2228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(pp, 2229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand(r3, Code::kConstantPoolOffset - Code::kHeaderSize)); 2230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2231e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r2, FieldMemOperand(r1, JSGeneratorObject::kContinuationOffset)); 2233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(r2); 2234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(r3, r3, r2); 2235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r2, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting))); 2236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r2, FieldMemOperand(r1, JSGeneratorObject::kContinuationOffset)); 2237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Jump(r3); 2238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&slow_resume); 2240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Otherwise, we push holes for the operand stack and call the runtime to fix 2243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // up the stack and the handlers. 2244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label push_operand_holes, call_resume; 2245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&push_operand_holes); 2246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(r3, r3, Operand(1), SetCC); 2247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(mi, &call_resume); 2248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r2); 2249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(&push_operand_holes); 2250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&call_resume); 2251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!result_register().is(r1)); 2252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(r1, result_register()); 2253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Smi::FromInt(resume_mode)); 2254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); 2255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Not reached: the runtime call returns elsewhere. 2256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ stop("not-reached"); 2257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Reach here when generator is closed. 2259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&closed_state); 2260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (resume_mode == JSGeneratorObject::NEXT) { 2261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return completed iterator result when generator is closed. 2262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); 2263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r2); 2264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pop value from top-of-stack slot; box result into result register. 2265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCreateIteratorResult(true); 2266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Throw the provided value. 2268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r0); 2269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kThrow, 1); 2270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done); 2272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Throw error if we attempt to operate on a running generator. 2274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&wrong_state); 2275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r1); 2276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); 2277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 2279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(result_register()); 2280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCreateIteratorResult(bool done) { 2284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label gc_required; 2285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label allocated; 2286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> map(isolate()->native_context()->iterator_result_map()); 2288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Allocate(map->instance_size(), r0, r2, r3, &gc_required, TAG_OBJECT); 2290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&allocated); 2291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&gc_required); 2293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Smi::FromInt(map->instance_size())); 2294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kAllocateInNewSpace, 1); 2295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(context_register(), 2296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand(fp, StandardFrameConstants::kContextOffset)); 2297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&allocated); 2299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r1, Operand(map)); 2300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(r2); 2301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r3, Operand(isolate()->factory()->ToBoolean(done))); 2302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r4, Operand(isolate()->factory()->empty_fixed_array())); 2303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(map->instance_size(), 5 * kPointerSize); 2304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 2305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset)); 2306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); 2307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r2, 2308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldMemOperand(r0, JSGeneratorObject::kResultValuePropertyOffset)); 2309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r3, 2310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldMemOperand(r0, JSGeneratorObject::kResultDonePropertyOffset)); 2311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Only the value field needs a write barrier, as the other values are in the 2313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // root set. 2314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteField(r0, JSGeneratorObject::kResultValuePropertyOffset, 2315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch r2, r3, kLRHasBeenSaved, kDontSaveFPRegs); 2316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { 2320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetSourcePosition(prop->position()); 2321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Literal* key = prop->key()->AsLiteral(); 2322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(LoadDescriptor::NameRegister(), Operand(key->value())); 2324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 2325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(VectorLoadICDescriptor::SlotRegister(), 2326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(Smi::FromInt(prop->PropertyFeedbackSlot()))); 2327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(NOT_CONTEXTUAL); 2328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); 2330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) { 2335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetSourcePosition(prop->position()); 2336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Literal* key = prop->key()->AsLiteral(); 2337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!key->value()->IsSmi()); 2338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(prop->IsSuperAccess()); 2339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SuperReference* super_ref = prop->obj()->AsSuperReference(); 2341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitLoadHomeObject(super_ref); 2342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(r0); 2343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(super_ref->this_var()); 2344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(key->value()); 2345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kLoadFromSuper, 3); 2346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { 2350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetSourcePosition(prop->position()); 2351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code(); 2352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 2353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(VectorLoadICDescriptor::SlotRegister(), 2354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(Smi::FromInt(prop->PropertyFeedbackSlot()))); 2355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic); 2356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, prop->PropertyFeedbackId()); 2358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, 2363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Token::Value op, 2364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OverwriteMode mode, 2365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* left_expr, 2366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* right_expr) { 2367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done, smi_case, stub_call; 2368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1 = r2; 2370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2 = r3; 2371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the arguments. 2373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register left = r1; 2374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register right = r0; 2375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(left); 2376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform combined smi check on both operands. 2378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ orr(scratch1, left, Operand(right)); 2379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 2380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JumpPatchSite patch_site(masm_); 2381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patch_site.EmitJumpIfSmi(scratch1, &smi_case); 2382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&stub_call); 2384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op, mode).code(); 2385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(code, expr->BinaryOperationFeedbackId()); 2386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patch_site.EmitPatchInfo(); 2387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done); 2388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&smi_case); 2390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Smi case. This code works the same way as the smi-smi case in the type 2391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // recording binary operation stub, see 2392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (op) { 2393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::SAR: 2394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ GetLeastBitsFromSmi(scratch1, right, 5); 2395e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(right, Operand(left, ASR, scratch1)); 2396e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bic(right, right, Operand(kSmiTagMask)); 2397e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 2398e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::SHL: { 2399e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiUntag(scratch1, left); 2400e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ GetLeastBitsFromSmi(scratch2, right, 5); 2401e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(scratch1, Operand(scratch1, LSL, scratch2)); 2402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TrySmiTag(right, scratch1, &stub_call); 2403e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 2404e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2405e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::SHR: { 2406e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiUntag(scratch1, left); 2407e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ GetLeastBitsFromSmi(scratch2, right, 5); 2408e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(scratch1, Operand(scratch1, LSR, scratch2)); 2409e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ tst(scratch1, Operand(0xc0000000)); 2410e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(ne, &stub_call); 2411e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiTag(right, scratch1); 2412e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 2413e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2414e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::ADD: 2415e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ add(scratch1, left, Operand(right), SetCC); 2416e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(vs, &stub_call); 2417e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(right, scratch1); 2418e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 2419e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::SUB: 2420e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ sub(scratch1, left, Operand(right), SetCC); 2421e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(vs, &stub_call); 2422e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(right, scratch1); 2423e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 2424e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::MUL: { 2425e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiUntag(ip, right); 2426e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ smull(scratch1, scratch2, left, ip); 2427e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(ip, Operand(scratch1, ASR, 31)); 2428e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmp(ip, Operand(scratch2)); 2429e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(ne, &stub_call); 2430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(scratch1, Operand::Zero()); 2431e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(right, Operand(scratch1), LeaveCC, ne); 2432e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(ne, &done); 2433e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ add(scratch2, right, Operand(left), SetCC); 2434e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(right, Operand(Smi::FromInt(0)), LeaveCC, pl); 2435e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(mi, &stub_call); 2436e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 2437e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2438e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::BIT_OR: 2439e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ orr(right, left, Operand(right)); 2440e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 2441e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::BIT_AND: 2442e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ and_(right, left, Operand(right)); 2443e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 2444e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::BIT_XOR: 2445e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ eor(right, left, Operand(right)); 2446e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 2447e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch default: 2448e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch UNREACHABLE(); 2449e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2450e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2451e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&done); 2452e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch context()->Plug(r0); 245380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 245480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 245580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, 2457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Token::Value op, 245880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen OverwriteMode mode) { 2459e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(r1); 2460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op, mode).code(); 24613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. 2462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(code, expr->BinaryOperationFeedbackId()); 24633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 24640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2465e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 2466e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2467e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 24683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitAssignment(Expression* expr) { 2469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->IsValidReferenceExpression()); 2470f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2471f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Left-hand side can only be a property, a global or a (parameter or local) 24723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // slot. 2473f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 2474f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke LhsKind assign_type = VARIABLE; 2475f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Property* prop = expr->AsProperty(); 2476f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (prop != NULL) { 2477f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke assign_type = (prop->key()->IsPropertyName()) 2478f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ? NAMED_PROPERTY 2479f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke : KEYED_PROPERTY; 2480f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2481f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2482f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (assign_type) { 2483f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case VARIABLE: { 2484f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Variable* var = expr->AsVariableProxy()->var(); 24850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EffectContext context(this); 24860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitVariableAssignment(var, Token::ASSIGN); 2487f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 2488f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2489f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case NAMED_PROPERTY: { 2490f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); // Preserve value. 24910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(prop->obj()); 2492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(StoreDescriptor::ReceiverRegister(), r0); 2493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(StoreDescriptor::ValueRegister()); // Restore value. 2494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(StoreDescriptor::NameRegister(), 2495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(prop->key()->AsLiteral()->value())); 2496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallStoreIC(); 2497f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 2498f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2499f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case KEYED_PROPERTY: { 2500f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ push(r0); // Preserve value. 25013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(prop->obj()); 25023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForAccumulatorValue(prop->key()); 2503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(StoreDescriptor::NameRegister(), r0); 2504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(StoreDescriptor::ValueRegister(), 2505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StoreDescriptor::ReceiverRegister()); 2506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = 2507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code(); 25083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallIC(ic); 2509f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 2510f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2511f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(r0); 2513f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2514f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2515f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( 2517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* var, MemOperand location) { 2518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(result_register(), location); 2519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->IsContextSlot()) { 2520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // RecordWrite may destroy all its register arguments. 2521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r3, result_register()); 2522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = Context::SlotOffset(var->index()); 2523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteContextSlot( 2524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch r1, offset, r3, r2, kLRHasBeenSaved, kDontSaveFPRegs); 2525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { 2530589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsUnallocated()) { 2531589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Global var, const, or let. 2532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(StoreDescriptor::NameRegister(), Operand(var->name())); 2533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand()); 2534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallStoreIC(); 2535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (op == Token::INIT_CONST_LEGACY) { 2537589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Const initializers need a write barrier. 2538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!var->IsParameter()); // No const parameters. 2539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->IsLookupSlot()) { 2540589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ push(r0); 2541589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ mov(r0, Operand(var->name())); 2542589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Push(cp, r0); // Context and name. 2543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); 2544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 2546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label skip; 2547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand location = VarOperand(var, r1); 2548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r2, location); 2549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); 2550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, &skip); 2551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitStoreToStackLocalOrContextSlot(var, location); 2552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&skip); 2553e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2554e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 25553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (var->mode() == LET && op != Token::INIT_LET) { 2556589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Non-initializing assignment to let variable needs a write barrier. 2557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!var->IsLookupSlot()); 2558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 2559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label assign; 2560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand location = VarOperand(var, r1); 2561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r3, location); 2562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); 2563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, &assign); 2564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r3, Operand(var->name())); 2565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r3); 2566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kThrowReferenceError, 1); 2567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform the assignment. 2568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&assign); 2569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitStoreToStackLocalOrContextSlot(var, location); 2570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (!var->is_const_mode() || op == Token::INIT_CONST) { 2572589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsLookupSlot()) { 2573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Assignment to var. 2574589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ push(r0); // Value. 2575589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ mov(r1, Operand(var->name())); 2576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r0, Operand(Smi::FromInt(strict_mode()))); 2577589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Push(cp, r1, r0); // Context, name, strict mode. 2578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kStoreLookupSlot, 4); 2579589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 2580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Assignment to var or initializing assignment to let/const in harmony 2581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // mode. 2582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((var->IsStackAllocated() || var->IsContextSlot())); 2583589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch MemOperand location = VarOperand(var, r1); 2584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (generate_debug_code_ && op == Token::INIT_LET) { 2585589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Check for an uninitialized let binding. 2586589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ ldr(r2, location); 2587589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); 2588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(eq, kLetBindingReInitialization); 2589589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 2590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitStoreToStackLocalOrContextSlot(var, location); 25913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 25923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2593589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Non-initializing assignments to consts are ignored. 25943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 25953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 25963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2597d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 2598d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a named store IC. 2599d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Property* prop = expr->target()->AsProperty(); 2600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(prop != NULL); 2601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(prop->key()->IsLiteral()); 2602d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2603e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source code position before IC call. 2604e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(expr->position()); 2605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(StoreDescriptor::NameRegister(), 2606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(prop->key()->AsLiteral()->value())); 2607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(StoreDescriptor::ReceiverRegister()); 2608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallStoreIC(expr->AssignmentFeedbackId()); 2609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 2611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(r0); 2612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2613d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2614d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2615d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 2616d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a keyed store IC. 2617d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source code position before IC call. 2619e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(expr->position()); 2620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister()); 2621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(StoreDescriptor::ValueRegister().is(r0)); 2622f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code(); 2624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, expr->AssignmentFeedbackId()); 2625d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 2627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(r0); 2628d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2629d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2630d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2631d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitProperty(Property* expr) { 2632d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Property"); 2633d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* key = expr->key(); 2634d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2635e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (key->IsPropertyName()) { 2636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!expr->IsSuperAccess()) { 2637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(expr->obj()); 2638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(LoadDescriptor::ReceiverRegister(), r0); 2639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitNamedPropertyLoad(expr); 2640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitNamedSuperPropertyLoad(expr); 2642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(expr->LoadId(), TOS_REG); 2644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(r0); 2645d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 26460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->obj()); 26470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->key()); 2648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(LoadDescriptor::NameRegister(), r0); 2649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(LoadDescriptor::ReceiverRegister()); 2650e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitKeyedPropertyLoad(expr); 2651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(r0); 2652d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2653d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2654d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 26553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::CallIC(Handle<Code> code, 2657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TypeFeedbackId ast_id) { 26583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ic_total_count_++; 2659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // All calls must have a predictable size in full-codegen code to ensure that 2660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the debugger can patch them correctly. 2661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Call(code, RelocInfo::CODE_TARGET, ast_id, al, 2662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NEVER_INLINE_TARGET_ADDRESS); 26633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 26643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Code common for calls using the IC. 2667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCallWithLoadIC(Call* expr) { 2668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* callee = expr->expression(); 2669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallICState::CallType call_type = 2671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch callee->IsVariableProxy() ? CallICState::FUNCTION : CallICState::METHOD; 2672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the target function. 2674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (call_type == CallICState::FUNCTION) { 2675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { StackValueContext context(this); 2676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitVariableLoad(callee->AsVariableProxy()); 2677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailout(callee, NO_REGISTERS); 26783e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 2679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push undefined as receiver. This is patched in the method prologue if it 2680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is a sloppy mode method. 2681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(isolate()->factory()->undefined_value()); 2682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the function from the receiver. 2684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(callee->IsProperty()); 2685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!callee->AsProperty()->IsSuperAccess()); 2686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0)); 2687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitNamedPropertyLoad(callee->AsProperty()); 2688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); 2689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the target function under the receiver. 2690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(ip, MemOperand(sp, 0)); 2691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(ip); 2692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r0, MemOperand(sp, kPointerSize)); 26933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCall(expr, call_type); 2696d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2697d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2698d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) { 2700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* callee = expr->expression(); 2701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(callee->IsProperty()); 2702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Property* prop = callee->AsProperty(); 2703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(prop->IsSuperAccess()); 2704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetSourcePosition(prop->position()); 2706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Literal* key = prop->key()->AsLiteral(); 2707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!key->value()->IsSmi()); 2708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the function from the receiver. 2709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register scratch = r1; 2710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SuperReference* super_ref = prop->obj()->AsSuperReference(); 2711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitLoadHomeObject(super_ref); 2712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(r0); 2713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(super_ref->this_var()); 2714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(r0); 2715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(scratch, MemOperand(sp, kPointerSize)); 2716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(scratch); 2717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(r0); 2718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(key->value()); 2719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Stack here: 2721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - home_object 2722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - this (receiver) 2723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - home_object <-- LoadFromSuper will pop here and below. 2724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - this (receiver) 2725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - key 2726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kLoadFromSuper, 3); 2727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Replace home_object with target function. 2729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r0, MemOperand(sp, kPointerSize)); 2730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Stack here: 2732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - target function 2733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - this (receiver) 2734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCall(expr, CallICState::METHOD); 2735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Code common for calls using the IC. 2739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, 2740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* key) { 27418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load the key. 27428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang VisitForAccumulatorValue(key); 27438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 2744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* callee = expr->expression(); 27458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 2746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the function from the receiver. 2747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(callee->IsProperty()); 2748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0)); 2749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(LoadDescriptor::NameRegister(), r0); 2750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitKeyedPropertyLoad(callee->AsProperty()); 2751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); 2752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the target function under the receiver. 2754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(ip, MemOperand(sp, 0)); 2755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(ip); 2756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r0, MemOperand(sp, kPointerSize)); 2757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCall(expr, CallICState::METHOD); 27599dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 27609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 27619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 2762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) { 2763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the arguments. 2764d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 2765d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 2766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { PreservePositionScope scope(masm()->positions_recorder()); 27673e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu for (int i = 0; i < arg_count; i++) { 27683e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForStackValue(args->at(i)); 27693e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 2770d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record source position of the IC call. 2773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetSourcePosition(expr->position()); 2774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = CallIC::initialize_stub( 2775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate(), arg_count, call_type); 2776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r3, Operand(Smi::FromInt(expr->CallFeedbackSlot()))); 27773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); 2778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Don't assign a type feedback id to the IC, since type feedback is provided 2779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // by the vector above. 2780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic); 2781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch RecordJSReturnSite(expr); 27833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Restore context register. 27843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 27850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->DropAndPlug(1, r0); 2786d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2787d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2788d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 27893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { 2790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r5: copy of the first argument or undefined if it doesn't exist. 2791e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (arg_count > 0) { 2792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r5, MemOperand(sp, arg_count * kPointerSize)); 2793e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 2794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); 2795e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2796e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r4: the receiver of the enclosing function. 2798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r4, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 2799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r3: the receiver of the enclosing function. 28013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int receiver_offset = 2 + info_->scope()->num_parameters(); 2802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r3, MemOperand(fp, receiver_offset * kPointerSize)); 2803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r2: strict mode. 2805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r2, Operand(Smi::FromInt(strict_mode()))); 2806e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r1: the start position of the scope the calls resides in. 28083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r1, Operand(Smi::FromInt(scope()->start_position()))); 28093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 28103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Do the runtime call. 2811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(r5); 2812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(r4, r3, r2, r1); 2813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 6); 2814e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2815e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2816e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2817d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCall(Call* expr) { 2818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG 2819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We want to verify that RecordJSReturnSite gets called on all paths 2820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // through this function. Avoid early returns. 2821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->return_is_recorded_ = false; 2822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif 2823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2824d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Call"); 2825589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Expression* callee = expr->expression(); 2826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Call::CallType call_type = expr->GetCallType(isolate()); 2827d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (call_type == Call::POSSIBLY_EVAL_CALL) { 2829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval 2830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to resolve the function we need to call and the receiver of the 2831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // call. Then we call the resolved function using the given 2832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // arguments. 2833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<Expression*>* args = expr->arguments(); 2834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int arg_count = args->length(); 2835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2836b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { PreservePositionScope pos_scope(masm()->positions_recorder()); 2837589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VisitForStackValue(callee); 28383e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); 28393e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ push(r2); // Reserved receiver slot. 2840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 28413e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Push the arguments. 28423e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu for (int i = 0; i < arg_count; i++) { 28433e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForStackValue(args->at(i)); 28443e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 28453e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 2846589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Push a copy of the function (found below the arguments) and 2847e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // resolve eval. 2848e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); 28491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(r1); 28503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitResolvePossiblyDirectEval(arg_count); 28513e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 28523e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // The runtime call returns a pair of values in r0 (function) and 28533e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // r1 (receiver). Touch up the stack with the right values. 28543e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize)); 28553e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ str(r1, MemOperand(sp, arg_count * kPointerSize)); 28563e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 2857f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2858f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Record source position for debugger. 2859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetSourcePosition(expr->position()); 2860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS); 28613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); 2862f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch RecordJSReturnSite(expr); 2864f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Restore context register. 2865f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 28660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->DropAndPlug(1, r0); 2867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (call_type == Call::GLOBAL_CALL) { 2868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCallWithLoadIC(expr); 2869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (call_type == Call::LOOKUP_SLOT_CALL) { 287159151504615d929945dc59db37bf1166937748c6Steve Block // Call to a lookup slot (dynamically introduced variable). 2872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableProxy* proxy = callee->AsVariableProxy(); 287359151504615d929945dc59db37bf1166937748c6Steve Block Label slow, done; 287459151504615d929945dc59db37bf1166937748c6Steve Block 2875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { PreservePositionScope scope(masm()->positions_recorder()); 28763e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Generate code for loading from variables potentially shadowed 28773e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // by eval-introduced variables. 2878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done); 28793e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 288059151504615d929945dc59db37bf1166937748c6Steve Block 288159151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&slow); 28820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Call the runtime to find the function to call (returned in r0) 288359151504615d929945dc59db37bf1166937748c6Steve Block // and the object holding it (returned in edx). 2884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!context_register().is(r2)); 2885589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ mov(r2, Operand(proxy->name())); 2886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(context_register(), r2); 2887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kLoadLookupSlot, 2); 288859151504615d929945dc59db37bf1166937748c6Steve Block __ Push(r0, r1); // Function, receiver. 288959151504615d929945dc59db37bf1166937748c6Steve Block 289059151504615d929945dc59db37bf1166937748c6Steve Block // If fast case code has been generated, emit code to push the 289159151504615d929945dc59db37bf1166937748c6Steve Block // function and receiver and have the slow path jump around this 289259151504615d929945dc59db37bf1166937748c6Steve Block // code. 289359151504615d929945dc59db37bf1166937748c6Steve Block if (done.is_linked()) { 289459151504615d929945dc59db37bf1166937748c6Steve Block Label call; 289559151504615d929945dc59db37bf1166937748c6Steve Block __ b(&call); 289659151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&done); 289759151504615d929945dc59db37bf1166937748c6Steve Block // Push function. 289859151504615d929945dc59db37bf1166937748c6Steve Block __ push(r0); 28993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // The receiver is implicitly the global receiver. Indicate this 29003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // by passing the hole to the call function stub. 2901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); 290259151504615d929945dc59db37bf1166937748c6Steve Block __ push(r1); 290359151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&call); 290459151504615d929945dc59db37bf1166937748c6Steve Block } 290559151504615d929945dc59db37bf1166937748c6Steve Block 2906257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The receiver is either the global receiver or an object found 2907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // by LoadContextSlot. 2908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCall(expr); 2909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (call_type == Call::PROPERTY_CALL) { 2910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Property* property = callee->AsProperty(); 2911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_named_call = property->key()->IsPropertyName(); 2912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // super.x() is handled in EmitCallWithLoadIC. 2913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (property->IsSuperAccess() && is_named_call) { 2914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitSuperCallWithLoadIC(expr); 2915d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 2916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 2917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PreservePositionScope scope(masm()->positions_recorder()); 2918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(property->obj()); 2919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (is_named_call) { 2921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCallWithLoadIC(expr); 2922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitKeyedCallWithLoadIC(expr, property->key()); 2924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2925d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 29263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 2927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(call_type == Call::OTHER_CALL); 2928589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Call to an arbitrary expression not handled specially above. 2929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { PreservePositionScope scope(masm()->positions_recorder()); 2930589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VisitForStackValue(callee); 29313e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 2932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); 2933d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ push(r1); 2934d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Emit function call. 2935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCall(expr); 29363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG 2939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // RecordJSReturnSite should have been called. 2940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->return_is_recorded_); 2941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif 29423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 29433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 29443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2945d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) { 2946d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CallNew"); 2947d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // According to ECMA-262, section 11.2.2, page 44, the function 2948d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // expression in new calls must be evaluated before the 2949d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // arguments. 295080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 295180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Push constructor on the stack. If it's not a function it's used as 295280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is 295380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ignored. 29540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->expression()); 2955d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2956d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push the arguments ("left-to-right") on the stack. 2957d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 2958d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 2959d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < arg_count; i++) { 29600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(i)); 2961d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2962d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2963d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call the construct call builtin that handles allocation and 2964d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // constructor invocation. 2965d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SetSourcePosition(expr->position()); 2966d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 296780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Load function and argument count into r1 and r0. 2968d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r0, Operand(arg_count)); 296980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); 2970d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record call targets in unoptimized code. 2972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_pretenuring_call_new) { 2973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot()); 2974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->AllocationSiteFeedbackSlot() == 2975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch expr->CallNewFeedbackSlot() + 1); 29763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 29773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(r2, FeedbackVector()); 2979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot()))); 2980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET); 29823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); 29833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutForId(expr->ReturnId(), TOS_REG); 29840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 2985d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2986d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2987d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 29883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { 29893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 2991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 299780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 29980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 29990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 3000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 30013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTst(r0); 3003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Split(eq, if_true, if_false, fall_through); 3004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 30050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 3006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3007f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 30093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) { 30103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 3012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 30130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 3014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 3016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 3017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 301880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 30190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 30200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 3021f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 30223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ NonNegativeSmiTst(r0); 302480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 3025f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 30260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 3027f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3028f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3029f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 30303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsObject(CallRuntime* expr) { 30313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 3033f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 30340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 3035f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3036f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 3037f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 3038f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 303980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 30400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 30410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 304280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 30431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r0, if_false); 3044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(ip, Heap::kNullValueRootIndex); 3045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r0, ip); 3046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 3047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); 3048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Undetectable objects behave like undefined when tested with typeof. 3049f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset)); 3050f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ tst(r1, Operand(1 << Map::kIsUndetectable)); 3051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, if_false); 3052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldrb(r1, FieldMemOperand(r2, Map::kInstanceTypeOffset)); 30533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp(r1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); 3054f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(lt, if_false); 30553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp(r1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); 30563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 305780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(le, if_true, if_false, fall_through); 3058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 30590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 3060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3061f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 30633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) { 30643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 30663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 30670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 30683bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 30693bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label materialize_true, materialize_false; 30703bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* if_true = NULL; 30713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* if_false = NULL; 307280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 30730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 30740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 30753bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 30761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r0, if_false); 30773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE); 30783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 307980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(ge, if_true, if_false, fall_through); 30803bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 30810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 30823bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch} 30833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 30843bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 30853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) { 30863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 3088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 30890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 3090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3091f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 3092f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 3093f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 309480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 30950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 30960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 3097f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 30981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r0, if_false); 3099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 3100f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); 3101f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ tst(r1, Operand(1 << Map::kIsUndetectable)); 31023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 310380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(ne, if_true, if_false, fall_through); 3104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 31050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 3106f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3107f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3108f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3109756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( 31103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallRuntime* expr) { 31113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 3113756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 31140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 3115756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 3116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false, skip_lookup; 3117756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label* if_true = NULL; 3118756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label* if_false = NULL; 311980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 31200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 31210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 3122756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 3123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AssertNotSmi(r0); 31248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 31258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 31268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ ldrb(ip, FieldMemOperand(r1, Map::kBitField2Offset)); 31278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ tst(ip, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf)); 3128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, &skip_lookup); 31298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 31308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Check for fast case object. Generate false result for slow case object. 31318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ ldr(r2, FieldMemOperand(r0, JSObject::kPropertiesOffset)); 31328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset)); 31338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ LoadRoot(ip, Heap::kHashTableMapRootIndex); 31348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ cmp(r2, ip); 31358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ b(eq, if_false); 31368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 3137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Look for valueOf name in the descriptor array, and indicate false if 3138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // found. Since we omit an enumeration index check, if it is added via a 3139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // transition that shares its descriptor array, this is a false positive. 3140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label entry, loop, done; 3141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Skip loop if no descriptors are valid. 3143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ NumberOfOwnDescriptors(r3, r1); 3144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r3, Operand::Zero()); 3145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(eq, &done); 3146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadInstanceDescriptors(r1, r4); 3148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r4: descriptor array. 3149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r3: valid entries in the descriptor array. 3150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ip, Operand(DescriptorArray::kDescriptorSize)); 3151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mul(r3, r3, ip); 3152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Calculate location of the first key name. 3153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(r4, r4, Operand(DescriptorArray::kFirstOffset - kHeapObjectTag)); 31548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Calculate the end of the descriptor array. 3155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r2, r4); 3156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(r2, r2, Operand(r3, LSL, kPointerSizeLog2)); 31578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 31588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Loop through all the keys in the descriptor array. If one of these is the 3159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // string "valueOf" the result is false. 3160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The use of ip to store the valueOf string assumes that it is not otherwise 31618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // used in the loop below. 3162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ip, Operand(isolate()->factory()->value_of_string())); 31638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ jmp(&entry); 31648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ bind(&loop); 31658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ ldr(r3, MemOperand(r4, 0)); 31668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ cmp(r3, ip); 31678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ b(eq, if_false); 3168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(r4, r4, Operand(DescriptorArray::kDescriptorSize * kPointerSize)); 31698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ bind(&entry); 31708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ cmp(r4, Operand(r2)); 31718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ b(ne, &loop); 31728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 3173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 3174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Set the bit in the map to indicate that there is no local valueOf field. 3176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldrb(r2, FieldMemOperand(r1, Map::kBitField2Offset)); 3177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ orr(r2, r2, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf)); 3178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ strb(r2, FieldMemOperand(r1, Map::kBitField2Offset)); 3179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&skip_lookup); 3181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If a valueOf property is not found on the object check that its 31838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // prototype is the un-modified String prototype. If not result is false. 31848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ ldr(r2, FieldMemOperand(r1, Map::kPrototypeOffset)); 31853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(r2, if_false); 31868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset)); 3187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r3, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); 3188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r3, FieldMemOperand(r3, GlobalObject::kNativeContextOffset)); 31898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ ldr(r3, ContextOperand(r3, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); 31908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ cmp(r2, r3); 31913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(eq, if_true, if_false, fall_through); 3193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 31940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 3195756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 3196756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 3197756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 31983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsFunction(CallRuntime* expr) { 31993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 3201f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 3203f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3204f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 3205f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 3206f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 320780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 32080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 32090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 3210f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r0, if_false); 3212589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CompareObjectType(r0, r1, r2, JS_FUNCTION_TYPE); 32133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 321480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 3215f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 3217f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) { 3221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 3223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); 3225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false; 3227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true = NULL; 3228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false = NULL; 3229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through = NULL; 3230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 3231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &if_true, &if_false, &fall_through); 3232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, if_false, DO_SMI_CHECK); 3234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); 3235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r1, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); 3236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r2, Operand(0x80000000)); 3237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r1, Operand(0x00000000), eq); 3238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(eq, if_true, if_false, fall_through); 3241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(if_true, if_false); 3243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 32463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsArray(CallRuntime* expr) { 32473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 3249f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 3251f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3252f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 3253f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 3254f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 325580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 32560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 32570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 3258f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r0, if_false); 3260f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); 32613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 326280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 3263f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 3265f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3266f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3267f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) { 32693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 3271f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 3273f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3274f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 3275f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 3276f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 327780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 32780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 32790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 3280f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r0, if_false); 3282f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); 32833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 328480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 3285f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 3287f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3288f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3289f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3290f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) { 3292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->arguments()->length() == 0); 3293f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3294f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 3295f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 3296f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 329780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 32980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 32990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 3300f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3301f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the frame pointer for the calling frame. 3302f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 3303f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3304f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Skip the arguments adaptor frame if it exists. 3305f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset)); 3306f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 3307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset), eq); 3308f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3309f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check the marker in the calling frame. 3310f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset)); 3311f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); 33123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 331380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 3314f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 33150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 3316f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3317f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3318f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 33193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) { 33203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 2); 3322f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the two objects into registers and perform the comparison. 33240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 33250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 3326f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 3328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 3329f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 333080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 33310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 33320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 3333f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3334f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r1); 3335f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r0, r1); 33363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 333780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 3338f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 33390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 3340f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3341f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3342f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 33433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitArguments(CallRuntime* expr) { 33443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 3346f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3347f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // ArgumentsAccessStub expects the key in edx and the formal 33480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // parameter count in r0. 33490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 3350f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ mov(r1, r0); 33513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); 3352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArgumentsAccessStub stub(isolate(), ArgumentsAccessStub::READ_ELEMENT); 3353f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 33540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3355f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3356f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3357f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 33583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { 3359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->arguments()->length() == 0); 3360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3361f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the number of formal parameters. 33623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); 3363f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3364f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the calling frame is an arguments adaptor frame. 3365f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 3366f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); 3367f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 3368f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3369f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Arguments adaptor case: Read the arguments length from the 3370f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // adaptor frame. 3371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset), eq); 3372f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 33730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3374f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3375f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3376f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 33773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitClassOf(CallRuntime* expr) { 33783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 3380f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done, null, function, non_function_constructor; 3381f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 33820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 3383f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3384f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi, we return null. 33851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r0, &null); 3386f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3387f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check that the object is a JS object but take special care of JS 3388f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // functions to make sure they have 'Function' as their class. 33893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Assume that there are only two callable types, and one of them is at 33903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // either end of the type range for JS object types. Saves extra comparisons. 33913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); 33923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CompareObjectType(r0, r0, r1, FIRST_SPEC_OBJECT_TYPE); 33933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Map is now in r0. 3394f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(lt, &null); 33953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == 33963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FIRST_SPEC_OBJECT_TYPE + 1); 33973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(eq, &function); 33983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r1, Operand(LAST_SPEC_OBJECT_TYPE)); 34003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == 34013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LAST_SPEC_OBJECT_TYPE - 1); 34023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(eq, &function); 34033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Assume that there is no larger type. 34043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1); 34053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 34063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if the constructor in the map is a JS function. 3407f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, FieldMemOperand(r0, Map::kConstructorOffset)); 3408f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE); 3409f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &non_function_constructor); 3410f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3411f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // r0 now contains the constructor function. Grab the 3412f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // instance class name from there. 3413f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset)); 3414f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, FieldMemOperand(r0, SharedFunctionInfo::kInstanceClassNameOffset)); 3415f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(&done); 3416f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3417f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Functions have class 'Function'. 3418f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&function); 3419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(r0, Heap::kFunction_stringRootIndex); 3420f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 3421f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3422f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Objects with a non-function constructor have class 'Object'. 3423f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&non_function_constructor); 3424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(r0, Heap::kObject_stringRootIndex); 3425f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 3426f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3427f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Non-JS objects have class null. 3428f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&null); 3429f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(r0, Heap::kNullValueRootIndex); 3430f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3431f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // All done. 3432f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 3433f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 34340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3435f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3436f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3437f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 34383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitSubString(CallRuntime* expr) { 3439f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the stub. 3440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SubStringStub stub(isolate()); 34413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 3); 34430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 34440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 34450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(2)); 3446f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 34470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3448f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3449f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3450f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 34513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) { 3452f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the stub. 3453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RegExpExecStub stub(isolate()); 34543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 4); 34560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 34570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 34580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(2)); 34590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(3)); 3460f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 34610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3462f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3463f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3464f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 34653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitValueOf(CallRuntime* expr) { 34663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 34680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); // Load the object. 3469f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3470f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 3471f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi return the object. 34721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r0, &done); 3473f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is not a value type, return the object. 3474f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE); 3475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset), eq); 3476f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3477f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 34780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3479f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3480f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3481f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 34823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitDateField(CallRuntime* expr) { 34833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 2); 3485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_NE(NULL, args->at(1)->AsLiteral()); 3486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value())); 34873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 34883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForAccumulatorValue(args->at(0)); // Load the object. 34893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label runtime, done, not_date_object; 34913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object = r0; 34923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register result = r0; 34933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch0 = r9; 34943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1 = r1; 34953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(object, ¬_date_object); 34973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareObjectType(object, scratch1, scratch1, JS_DATE_TYPE); 3498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, ¬_date_object); 34993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 35003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (index->value() == 0) { 35013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset)); 3502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done); 35033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 35043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (index->value() < JSDate::kFirstUncachedField) { 35053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); 35063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(scratch1, Operand(stamp)); 35073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(scratch1, MemOperand(scratch1)); 35083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(scratch0, FieldMemOperand(object, JSDate::kCacheStampOffset)); 35093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(scratch1, scratch0); 35103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &runtime); 35113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset + 35123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kPointerSize * index->value())); 35133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done); 35143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 35153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&runtime); 35163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PrepareCallCFunction(2, scratch1); 35173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r1, Operand(index)); 35183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); 3519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done); 35203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(¬_date_object); 3523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kThrowNotDateError, 0); 3524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 35253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(r0); 35263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 35273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 35283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { 3530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(3, args->length()); 3532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register string = r0; 3534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register index = r1; 3535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value = r2; 3536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(0)); // index 3538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(1)); // value 3539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(2)); // string 3540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(index, value); 3541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code) { 3543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTst(value); 3544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(eq, kNonSmiValue); 3545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTst(index); 3546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(eq, kNonSmiIndex); 3547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(index, index); 3548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; 3549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type); 3550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(index, index); 3551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(value, value); 3554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(ip, 3555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch string, 3556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 3557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ strb(value, MemOperand(ip, index, LSR, kSmiTagSize)); 3558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(string); 3559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { 3563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(3, args->length()); 3565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register string = r0; 3567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register index = r1; 3568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value = r2; 3569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(0)); // index 3571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(1)); // value 3572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(2)); // string 3573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(index, value); 3574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code) { 3576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTst(value); 3577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(eq, kNonSmiValue); 3578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTst(index); 3579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(eq, kNonSmiIndex); 3580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(index, index); 3581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; 3582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type); 3583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(index, index); 3584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(value, value); 3587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(ip, 3588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch string, 3589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 3590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 3591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ strh(value, MemOperand(ip, index)); 3592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(string); 3593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 35973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathPow(CallRuntime* expr) { 3598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the runtime function. 35993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 2); 36010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 36020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 3603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MathPowStub stub(isolate(), MathPowStub::ON_STACK); 3604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallStub(&stub); 36050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3607f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3608f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 36093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { 36103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 2); 36120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); // Load the object. 36130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); // Load the value. 3614f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ pop(r1); // r0 = value. r1 = object. 3615f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3616f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 3617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi, return the value. 36181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r1, &done); 3619f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3620f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is not a value type, return the value. 3621f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE); 3622f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, &done); 3623f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3624f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Store the value. 3625f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset)); 3626f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Update the write barrier. Save the value as it will be 3627f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // overwritten by the write barrier code and is needed afterward. 36283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r2, r0); 36293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField( 36303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r1, JSValue::kValueOffset, r2, r3, kLRHasBeenSaved, kDontSaveFPRegs); 3631f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 36330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3634f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3635f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3636f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 36373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { 36383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(args->length(), 1); 3640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the argument into r0 and call the stub. 3641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); 3642f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NumberToStringStub stub(isolate()); 3644f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 36450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3646f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3647f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3648f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 36493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { 36503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 36520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 3653f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 36547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 36557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharFromCodeGenerator generator(r0, r1); 36567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 36577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 3658f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 36597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 36607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 3661f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3662f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 36630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r1); 3664f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3665f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3666f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 36673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { 36683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 2); 36700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 36710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 36727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 36737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register object = r1; 36747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = r0; 36757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = r3; 36767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 36777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(object); 36787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 36797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label need_conversion; 36807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 36817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 36827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharCodeAtGenerator generator(object, 36837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch index, 36847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch result, 36857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 36867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 36877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &index_out_of_range, 36887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch STRING_INDEX_IS_NUMBER); 36897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 36907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 36917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 36927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_out_of_range); 36937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // When the index is out of range, the spec requires us to return 36947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // NaN. 36957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kNanValueRootIndex); 36967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 36977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 36987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&need_conversion); 36997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Load the undefined value into the result register, which will 37007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // trigger conversion. 37017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kUndefinedValueRootIndex); 37027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 37037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 37047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 37057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 37067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 37077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&done); 37080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(result); 37097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 37107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 37117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 37123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) { 37133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 2); 37150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 37160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 37177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 37187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register object = r1; 37197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = r0; 37203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch = r3; 37217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = r0; 37227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 37237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(object); 37247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 37257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label need_conversion; 37267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 37277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 37287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharAtGenerator generator(object, 37297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch index, 37303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 37317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch result, 37327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 37337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 37347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &index_out_of_range, 37357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch STRING_INDEX_IS_NUMBER); 37367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 37377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 37387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 37397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_out_of_range); 37407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // When the index is out of range, the spec requires us to return 37417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // the empty string. 3742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(result, Heap::kempty_stringRootIndex); 37437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 37447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 37457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&need_conversion); 37467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Move smi zero into the result register, which will trigger 37477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // conversion. 37487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(result, Operand(Smi::FromInt(0))); 37497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 37507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 37517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 37527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 37537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 37547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&done); 37550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(result); 3756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3757f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 37587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 37593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { 37603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(2, args->length()); 37620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 3763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(1)); 3764f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(r1); 3766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED); 3767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 37680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3771f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 37723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { 37733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(2, args->length()); 37750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 37760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 3777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StringCompareStub stub(isolate()); 3779e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CallStub(&stub); 37800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3781f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3782f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 37843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { 37853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() >= 2); 3787f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int arg_count = args->length() - 2; // 2 ~ receiver and function. 3789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = 0; i < arg_count + 1; i++) { 3790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VisitForStackValue(args->at(i)); 3791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VisitForAccumulatorValue(args->last()); // Function. 3793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label runtime, done; 3795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for non-function argument (including proxy). 3796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(r0, &runtime); 3797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE); 3798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, &runtime); 37993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // InvokeFunction requires the function in r1. Move it in there. 3801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(r1, result_register()); 3802f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ParameterCount count(arg_count); 3803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeFunction(r1, count, CALL_FUNCTION, NullCallWrapper()); 3804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 38053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done); 38063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&runtime); 38083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 38093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kCall, args->length()); 38103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 38113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 38163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { 3817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RegExpConstructResultStub stub(isolate()); 38183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 3); 38200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 38210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 3822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(2)); 3823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(r1); 3824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(r2); 3825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ CallStub(&stub); 38260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3827f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 38303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { 38313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(2, args->length()); 3833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_NE(NULL, args->at(0)->AsLiteral()); 3834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->value()))->value(); 3835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<FixedArray> jsfunction_result_caches( 3837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate()->native_context()->jsfunction_result_caches()); 3838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (jsfunction_result_caches->length() <= cache_id) { 3839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Abort(kAttemptToUseUndefinedCache); 3840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 38410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 3843f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3844f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 38450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 3846f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3847f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register key = r0; 3848f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register cache = r1; 3849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(cache, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); 3850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(cache, FieldMemOperand(cache, GlobalObject::kNativeContextOffset)); 385159151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(cache, ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX)); 3852f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(cache, 3853f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FieldMemOperand(cache, FixedArray::OffsetOfElementAt(cache_id))); 3854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3855f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3856f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done, not_found; 3857f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r2, FieldMemOperand(cache, JSFunctionResultCache::kFingerOffset)); 3858f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // r2 now holds finger offset as a smi. 3859f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ add(r3, cache, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 3860f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // r3 now points to the start of fixed array elements. 3861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r2, MemOperand::PointerAddressFromSmiKey(r3, r2, PreIndex)); 3862f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Note side effect of PreIndex: r3 now points to the key of the pair. 3863f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(key, r2); 3864f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(ne, ¬_found); 3865f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3866f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ ldr(r0, MemOperand(r3, kPointerSize)); 3867f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(&done); 3868f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3869f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(¬_found); 3870f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Call runtime to perform the lookup. 3871f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(cache, key); 3872f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kGetFromCache, 2); 3873f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3874f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 38750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 3876f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3877f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3878f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 38793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { 38803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 38810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 388280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 388380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label materialize_true, materialize_false; 388480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true = NULL; 388580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false = NULL; 388680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 38870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 38880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 388980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 389080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset)); 389180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ tst(r0, Operand(String::kContainsCachedArrayIndexMask)); 38923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Split(eq, if_true, if_false, fall_through); 389480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 38950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 389680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 389780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 389880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 38993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) { 39003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 39020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 3903e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AssertString(r0); 3905e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 390680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset)); 390780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ IndexFromHash(r0, r0); 3908e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 39090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 391080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 391180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 391280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 3913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitFastOneByteArrayJoin(CallRuntime* expr) { 3914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label bailout, done, one_char_separator, long_separator, non_trivial_array, 3915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch not_size_one_array, loop, empty_separator_loop, one_char_separator_loop, 3916e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch one_char_separator_loop_entry, long_separator_loop; 39173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 2); 3919e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitForStackValue(args->at(1)); 3920e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitForAccumulatorValue(args->at(0)); 3921e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3922e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // All aliases of the same register have disjoint lifetimes. 3923e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register array = r0; 3924e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register elements = no_reg; // Will be r0. 3925e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register result = no_reg; // Will be r0. 3926e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register separator = r1; 3927e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register array_length = r2; 3928e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register result_pos = no_reg; // Will be r2 3929e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register string_length = r3; 3930e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register string = r4; 3931e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register element = r5; 3932e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register elements_end = r6; 3933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch = r9; 3934e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3935e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Separator operand is on the stack. 3936e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ pop(separator); 3937e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3938e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Check that the array is a JSArray. 3939e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(array, &bailout); 3940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareObjectType(array, scratch, array_length, JS_ARRAY_TYPE); 3941e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(ne, &bailout); 3942e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3943e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Check that the array has fast elements. 3944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CheckFastElements(scratch, array_length, &bailout); 3945e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3946e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // If the array has length zero, return the empty string. 3947e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(array_length, FieldMemOperand(array, JSArray::kLengthOffset)); 3948e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiUntag(array_length, SetCC); 3949e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(ne, &non_trivial_array); 3950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(r0, Heap::kempty_stringRootIndex); 3951e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(&done); 3952e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3953e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&non_trivial_array); 3954e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3955e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Get the FixedArray containing array's elements. 3956e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch elements = array; 3957e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(elements, FieldMemOperand(array, JSArray::kElementsOffset)); 3958e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch array = no_reg; // End of array's live range. 3959e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that all array elements are sequential one-byte strings, and 3961e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // accumulate the sum of their lengths, as a smi-encoded value. 3962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(string_length, Operand::Zero()); 3963e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ add(element, 3964e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 3965e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2)); 3966e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Loop condition: while (element < elements_end). 3967e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Live values in registers: 3968e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // elements: Fixed array of strings. 3969e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // array_length: Length of the fixed array of strings (not smi) 3970e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // separator: Separator string 3971e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // string_length: Accumulated sum of string lengths (smi). 3972e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // element: Current array element. 3973e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // elements_end: Array end. 3974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (generate_debug_code_) { 3975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(array_length, Operand::Zero()); 3976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(gt, kNoEmptyArraysHereInEmitFastOneByteArrayJoin); 3977e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3978e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&loop); 3979e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); 3980e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(string, &bailout); 3981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(scratch, FieldMemOperand(string, HeapObject::kMapOffset)); 3982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); 3983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfInstanceTypeIsNotSequentialOneByte(scratch, scratch, &bailout); 3984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(scratch, FieldMemOperand(string, SeqOneByteString::kLengthOffset)); 3985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(string_length, string_length, Operand(scratch), SetCC); 3986e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(vs, &bailout); 3987e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmp(element, elements_end); 3988e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(lt, &loop); 3989e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3990e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // If array_length is 1, return elements[0], a string. 3991e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmp(array_length, Operand(1)); 3992e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(ne, ¬_size_one_array); 3993e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(r0, FieldMemOperand(elements, FixedArray::kHeaderSize)); 3994e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(&done); 3995e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3996e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(¬_size_one_array); 3997e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3998e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Live values in registers: 3999e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // separator: Separator string 4000e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // array_length: Length of the array. 4001e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // string_length: Sum of string lengths (smi). 4002e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // elements: FixedArray of strings. 4003e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the separator is a flat one-byte string. 4005e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(separator, &bailout); 4006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(scratch, FieldMemOperand(separator, HeapObject::kMapOffset)); 4007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); 4008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfInstanceTypeIsNotSequentialOneByte(scratch, scratch, &bailout); 4009e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4010e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Add (separator length times array_length) - separator length to the 4011e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // string_length to get the length of the result string. array_length is not 4012e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // smi but the other values are, so the result is a smi 4013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(scratch, FieldMemOperand(separator, SeqOneByteString::kLengthOffset)); 4014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(string_length, string_length, Operand(scratch)); 4015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ smull(scratch, ip, array_length, scratch); 4016e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Check for smi overflow. No overflow if higher 33 bits of 64-bit result are 4017e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // zero. 4018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(ip, Operand::Zero()); 4019e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(ne, &bailout); 4020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ tst(scratch, Operand(0x80000000)); 4021e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(ne, &bailout); 4022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(string_length, string_length, Operand(scratch), SetCC); 4023e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(vs, &bailout); 4024e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiUntag(string_length); 4025e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4026e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Get first element in the array to free up the elements register to be used 4027e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // for the result. 4028e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ add(element, 4029e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 4030e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch result = elements; // End of live range for elements. 4031e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch elements = no_reg; 4032e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Live values in registers: 4033e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // element: First array element 4034e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // separator: Separator string 4035e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // string_length: Length of result string (not smi) 4036e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // array_length: Length of the array. 4037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AllocateOneByteString(result, string_length, scratch, 4038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch string, // used as scratch 4039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch elements_end, // used as scratch 4040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &bailout); 4041e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Prepare for looping. Set up elements_end to end of the array. Set 4042e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // result_pos to the position of the result where to write the first 4043e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // character. 4044e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2)); 4045e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch result_pos = array_length; // End of live range for array_length. 4046e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch array_length = no_reg; 4047e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ add(result_pos, 4048e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch result, 4049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 4050e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4051e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Check the length of the separator. 4052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(scratch, FieldMemOperand(separator, SeqOneByteString::kLengthOffset)); 4053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(scratch, Operand(Smi::FromInt(1))); 4054e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(eq, &one_char_separator); 4055e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(gt, &long_separator); 4056e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4057e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Empty separator case 4058e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&empty_separator_loop); 4059e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Live values in registers: 4060e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // result_pos: the position to which we are currently copying characters. 4061e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // element: Current array element. 4062e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // elements_end: Array end. 4063e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4064e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Copy next array element to the result. 4065e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); 4066e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset)); 4067e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiUntag(string_length); 4068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(string, 4069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch string, 4070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 4071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CopyBytes(string, result_pos, string_length, scratch); 4072e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmp(element, elements_end); 4073e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(lt, &empty_separator_loop); // End while (element < elements_end). 4074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(result.is(r0)); 4075e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(&done); 4076e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4077e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // One-character separator case 4078e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&one_char_separator); 4079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Replace separator with its one-byte character value. 4080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldrb(separator, FieldMemOperand(separator, SeqOneByteString::kHeaderSize)); 4081e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Jump into the loop after the code that copies the separator, so the first 4082e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // element is not preceded by a separator 4083e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ jmp(&one_char_separator_loop_entry); 4084e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4085e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&one_char_separator_loop); 4086e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Live values in registers: 4087e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // result_pos: the position to which we are currently copying characters. 4088e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // element: Current array element. 4089e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // elements_end: Array end. 4090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // separator: Single separator one-byte char (in lower byte). 4091e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4092e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Copy the separator character to the result. 4093e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ strb(separator, MemOperand(result_pos, 1, PostIndex)); 4094e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4095e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Copy next array element to the result. 4096e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&one_char_separator_loop_entry); 4097e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); 4098e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset)); 4099e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiUntag(string_length); 4100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(string, 4101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch string, 4102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 4103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CopyBytes(string, result_pos, string_length, scratch); 4104e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmp(element, elements_end); 4105e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(lt, &one_char_separator_loop); // End while (element < elements_end). 4106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(result.is(r0)); 4107e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(&done); 4108e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4109e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Long separator case (separator is more than one character). Entry is at the 4110e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // label long_separator below. 4111e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&long_separator_loop); 4112e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Live values in registers: 4113e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // result_pos: the position to which we are currently copying characters. 4114e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // element: Current array element. 4115e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // elements_end: Array end. 4116e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // separator: Separator string. 4117e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4118e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Copy the separator to the result. 4119e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(string_length, FieldMemOperand(separator, String::kLengthOffset)); 4120e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiUntag(string_length); 4121e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ add(string, 4122e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch separator, 4123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 4124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CopyBytes(string, result_pos, string_length, scratch); 4125e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4126e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&long_separator); 4127e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); 4128e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset)); 4129e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiUntag(string_length); 4130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(string, 4131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch string, 4132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 4133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CopyBytes(string, result_pos, string_length, scratch); 4134e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmp(element, elements_end); 4135e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(lt, &long_separator_loop); // End while (element < elements_end). 4136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(result.is(r0)); 4137e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(&done); 4138e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4139e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&bailout); 41408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 4141e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&done); 41428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang context()->Plug(r0); 41438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 41448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 41458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 4146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { 4147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->arguments()->length() == 0); 4148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference debug_is_active = 4149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::debug_is_active_address(isolate()); 4150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ip, Operand(debug_is_active)); 4151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldrb(r0, MemOperand(ip)); 4152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(r0); 4153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(r0); 4154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4157d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 4158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->function() != NULL && 4159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch expr->function()->intrinsic_type == Runtime::INLINE) { 4160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ InlineRuntimeCall"); 4161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitInlineRuntimeCall(expr); 4162f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 4163f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 4164f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 41653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ CallRuntime"); 41663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ZoneList<Expression*>* args = expr->arguments(); 4167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int arg_count = args->length(); 41683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->is_jsruntime()) { 4170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the builtins object as the receiver. 4171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register receiver = LoadDescriptor::ReceiverRegister(); 4172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(receiver, GlobalObjectOperand()); 4173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(receiver, FieldMemOperand(receiver, GlobalObject::kBuiltinsOffset)); 4174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(receiver); 4175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the function from the receiver. 4177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(LoadDescriptor::NameRegister(), Operand(expr->name())); 4178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 4179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(VectorLoadICDescriptor::SlotRegister(), 4180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(Smi::FromInt(expr->CallRuntimeFeedbackSlot()))); 4181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(NOT_CONTEXTUAL); 4182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); 4184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 41853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the target function under the receiver. 4187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(ip, MemOperand(sp, 0)); 4188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(ip); 4189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r0, MemOperand(sp, kPointerSize)); 4190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the arguments ("left-to-right"). 4192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int arg_count = args->length(); 4193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < arg_count; i++) { 4194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(i)); 4195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record source position of the IC call. 4198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetSourcePosition(expr->position()); 4199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS); 4200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); 4201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallStub(&stub); 4202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Restore context register. 4204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 4205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->DropAndPlug(1, r0); 4207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 4208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the arguments ("left-to-right"). 4209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < arg_count; i++) { 4210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(i)); 4211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4213d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call the C runtime function. 4214d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(expr->function(), arg_count); 4215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(r0); 4216d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 4217d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 4218d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4219d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4220d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 4221d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 4222f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Token::DELETE: { 4223f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); 4224589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Property* property = expr->expression()->AsProperty(); 4225589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VariableProxy* proxy = expr->expression()->AsVariableProxy(); 4226e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4227589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (property != NULL) { 4228589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VisitForStackValue(property->obj()); 4229589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VisitForStackValue(property->key()); 4230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r1, Operand(Smi::FromInt(strict_mode()))); 423169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ push(r1); 423269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 423369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch context()->Plug(r0); 4234589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (proxy != NULL) { 4235589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* var = proxy->var(); 4236e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Delete of an unqualified identifier is disallowed in strict mode 4237589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // but "delete this" is allowed. 4238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(strict_mode() == SLOPPY || var->is_this()); 4239589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsUnallocated()) { 4240e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(r2, GlobalObjectOperand()); 4241e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(r1, Operand(var->name())); 4242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r0, Operand(Smi::FromInt(SLOPPY))); 4243e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Push(r2, r1, r0); 4244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 4245e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch context()->Plug(r0); 4246589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (var->IsStackAllocated() || var->IsContextSlot()) { 4247e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Result of deleting non-global, non-dynamic variables is false. 4248e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The subexpression does not have side effects. 4249589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch context()->Plug(var->is_this()); 4250e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 4251e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Non-global variable. Call the runtime to try to delete from the 4252e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // context where the variable was introduced. 4253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!context_register().is(r2)); 4254e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(r2, Operand(var->name())); 4255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(context_register(), r2); 4256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kDeleteLookupSlot, 2); 4257e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch context()->Plug(r0); 4258e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 42591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 4260e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Result of deleting non-property, non-variable reference is true. 4261e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The subexpression may have side effects. 4262e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitForEffect(expr->expression()); 4263e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch context()->Plug(true); 4264f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 4265f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 4266f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 4267f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 4268d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::VOID: { 4269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (VOID)"); 4270e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForEffect(expr->expression()); 42710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(Heap::kUndefinedValueRootIndex); 4272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 4273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 4274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4275d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::NOT: { 4276d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 4277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (context()->IsEffect()) { 4278e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Unary NOT has no side effects so it's only necessary to visit the 4279e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // subexpression. Match the optimizing compiler by not branching. 4280e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitForEffect(expr->expression()); 42813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (context()->IsTest()) { 42823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const TestContext* test = TestContext::cast(context()); 42833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The labels are swapped for the recursive call. 42843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForControl(expr->expression(), 42853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test->false_label(), 42863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test->true_label(), 42873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test->fall_through()); 42883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(test->true_label(), test->false_label()); 4289e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 42903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We handle value contexts explicitly rather than simply visiting 42913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // for control and plugging the control flow into the context, 42923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // because we need to prepare a pair of extra administrative AST ids 42933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // for the optimizing compiler. 4294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue()); 42953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label materialize_true, materialize_false, done; 42963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForControl(expr->expression(), 42973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &materialize_false, 42983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &materialize_true, 42993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &materialize_true); 43003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&materialize_true); 43013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS); 43023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r0, Heap::kTrueValueRootIndex); 43033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (context()->IsStackValue()) __ push(r0); 43043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done); 43053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&materialize_false); 43063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS); 43073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r0, Heap::kFalseValueRootIndex); 43083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (context()->IsStackValue()) __ push(r0); 43093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 4310e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 4311d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 4312d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 4313d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4314d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::TYPEOF: { 4315d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 43160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { StackValueContext context(this); 43170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForTypeofValue(expr->expression()); 43180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 4319d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kTypeof, 1); 43200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 4321d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 43223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 4323d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4324d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 4325d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 43263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 4327d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 4328d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4329d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4330d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 4331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->expression()->IsValidReferenceExpression()); 4332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4333d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CountOperation"); 433480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen SetSourcePosition(expr->position()); 433580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 4336e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Expression can only be a property, a global or a (parameter or local) 43373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // slot. 4338e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 4339e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LhsKind assign_type = VARIABLE; 4340e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Property* prop = expr->expression()->AsProperty(); 4341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // In case of a property we use the uninitialized expression context 4342e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // of the key to detect a named property. 4343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (prop != NULL) { 4344e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke assign_type = 4345e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 4346d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 4347e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4348e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Evaluate expression and get value. 4349e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == VARIABLE) { 4350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->expression()->AsVariableProxy()->var() != NULL); 43510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AccumulatorValueContext context(this); 43523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch EmitVariableLoad(expr->expression()->AsVariableProxy()); 43533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 4354e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Reserve space for result of postfix operation. 43550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (expr->is_postfix() && !context()->IsEffect()) { 4356e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(ip, Operand(Smi::FromInt(0))); 4357e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(ip); 4358e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4359e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == NAMED_PROPERTY) { 4360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Put the object both on the stack and in the register. 4361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(prop->obj()); 4362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0)); 4363e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitNamedPropertyLoad(prop); 4364e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 43653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(prop->obj()); 4366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(prop->key()); 4367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(LoadDescriptor::ReceiverRegister(), 4368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand(sp, 1 * kPointerSize)); 4369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(LoadDescriptor::NameRegister(), MemOperand(sp, 0)); 4370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitKeyedPropertyLoad(prop); 4371e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4372d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 4373d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We need a second deoptimization point after loading the value 4375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // in case evaluating the property load my have a side effect. 43768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (assign_type == VARIABLE) { 43778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PrepareForBailout(expr->expression(), TOS_REG); 43788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 4379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(prop->LoadId(), TOS_REG); 43808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 4381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Inline smi case if we are in a loop. 4383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label stub_call, done; 4384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JumpPatchSite patch_site(masm_); 4385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int count_value = expr->op() == Token::INC ? 1 : -1; 4387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (ShouldInlineSmiCase(expr->op())) { 4388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow; 4389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patch_site.EmitJumpIfNotSmi(r0, &slow); 4390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save result for postfix expressions. 4392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->is_postfix()) { 4393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!context()->IsEffect()) { 4394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save the result on the stack. If we have a named or keyed property 4395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // we store the result under the receiver that is currently on top 4396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of the stack. 4397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (assign_type) { 4398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case VARIABLE: 4399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r0); 4400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case NAMED_PROPERTY: 4402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r0, MemOperand(sp, kPointerSize)); 4403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case KEYED_PROPERTY: 4405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r0, MemOperand(sp, 2 * kPointerSize)); 4406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC); 4412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(vc, &done); 4413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call stub. Undo operation first. 4414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(r0, r0, Operand(Smi::FromInt(count_value))); 4415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&stub_call); 4416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&slow); 4417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ToNumberStub convert_stub(isolate()); 44191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CallStub(&convert_stub); 4420e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4421e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save result for postfix expressions. 4422e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 44230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 44240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Save the result on the stack. If we have a named or keyed property 44250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // we store the result under the receiver that is currently on top 44260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // of the stack. 44270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen switch (assign_type) { 44280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case VARIABLE: 44290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(r0); 44300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 44310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case NAMED_PROPERTY: 44320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ str(r0, MemOperand(sp, kPointerSize)); 44330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 44340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case KEYED_PROPERTY: 44350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ str(r0, MemOperand(sp, 2 * kPointerSize)); 44360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 44370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 4438e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4439e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4440e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4441d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 4442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&stub_call); 4443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r1, r0); 4444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r0, Operand(Smi::FromInt(count_value))); 4445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Record position before stub call. 4447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetSourcePosition(expr->position()); 4448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> code = 4450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeFactory::BinaryOpIC(isolate(), Token::ADD, NO_OVERWRITE).code(); 4451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(code, expr->CountBinOpFeedbackId()); 44523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 4453d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&done); 4454e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4455e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store the value returned in r0. 4456e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (assign_type) { 4457e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case VARIABLE: 4458e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 44590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { EffectContext context(this); 44600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 44610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Token::ASSIGN); 4462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context.Plug(r0); 44640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 44650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // For all contexts except EffectConstant We have the result on 4466e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // top of the stack. 44670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 44680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 4469e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4470e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 4471e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 44720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Token::ASSIGN); 4473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(r0); 4475e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4476d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 4477e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case NAMED_PROPERTY: { 4478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(StoreDescriptor::NameRegister(), 4479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(prop->key()->AsLiteral()->value())); 4480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(StoreDescriptor::ReceiverRegister()); 4481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallStoreIC(expr->CountStoreFeedbackId()); 4482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4483e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 44840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 44850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 4486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4487e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 44880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 4489e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4490d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 4491d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 4492e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case KEYED_PROPERTY: { 4493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(StoreDescriptor::ReceiverRegister(), 4494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StoreDescriptor::NameRegister()); 4495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = 4496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code(); 4497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, expr->CountStoreFeedbackId()); 4498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4499e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 45000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 45010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 4502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4503e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 45040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 4505e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4506d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 4507d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 45083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 45093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 45103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 45113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 45120d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::VisitForTypeofValue(Expression* expr) { 4513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!context()->IsEffect()); 4514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!context()->IsTest()); 451580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen VariableProxy* proxy = expr->AsVariableProxy(); 4516589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (proxy != NULL && proxy->var()->IsUnallocated()) { 4517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Global variable"); 4518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); 4519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(LoadDescriptor::NameRegister(), Operand(proxy->name())); 4520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 4521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(VectorLoadICDescriptor::SlotRegister(), 4522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(Smi::FromInt(proxy->VariableFeedbackSlot()))); 4523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 452480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Use a regular load, not a contextual load, to avoid a reference 452580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // error. 4526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(NOT_CONTEXTUAL); 4527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailout(expr, TOS_REG); 45280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 4529589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { 4530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Lookup slot"); 453159151504615d929945dc59db37bf1166937748c6Steve Block Label done, slow; 453259151504615d929945dc59db37bf1166937748c6Steve Block 453359151504615d929945dc59db37bf1166937748c6Steve Block // Generate code for loading from variables potentially shadowed 453459151504615d929945dc59db37bf1166937748c6Steve Block // by eval-introduced variables. 4535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitDynamicLookupFastCase(proxy, INSIDE_TYPEOF, &slow, &done); 453659151504615d929945dc59db37bf1166937748c6Steve Block 453759151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&slow); 453880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ mov(r0, Operand(proxy->name())); 453980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Push(cp, r0); 4540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kLoadLookupSlotNoReferenceError, 2); 4541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailout(expr, TOS_REG); 454259151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&done); 454359151504615d929945dc59db37bf1166937748c6Steve Block 45440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 454580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 454680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // This expression cannot throw a reference error at the top level. 45473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitInDuplicateContext(expr); 4548d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 4549d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 4550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 45513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 45523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, 45533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Expression* sub_expr, 45543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> check) { 45553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label materialize_true, materialize_false; 45563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* if_true = NULL; 45573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* if_false = NULL; 45583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* fall_through = NULL; 45593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 45603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &if_true, &if_false, &fall_through); 45613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 45620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { AccumulatorValueContext context(this); 45633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForTypeofValue(sub_expr); 45640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 45653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Factory* factory = isolate()->factory(); 4568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (String::Equals(check, factory->number_string())) { 4569e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(r0, if_true); 457080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); 457180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); 457280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r0, ip); 457380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 4574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->string_string())) { 4575e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(r0, if_false); 457680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for undetectable objects => false. 4577e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CompareObjectType(r0, r0, r1, FIRST_NONSTRING_TYPE); 4578e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(ge, if_false); 457980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); 4580e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ tst(r1, Operand(1 << Map::kIsUndetectable)); 4581e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Split(eq, if_true, if_false, fall_through); 4582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->symbol_string())) { 4583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(r0, if_false); 4584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareObjectType(r0, r0, r1, SYMBOL_TYPE); 4585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(eq, if_true, if_false, fall_through); 4586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->boolean_string())) { 4587e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CompareRoot(r0, Heap::kTrueValueRootIndex); 4588f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 4589e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CompareRoot(r0, Heap::kFalseValueRootIndex); 459080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 4591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->undefined_string())) { 4592e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CompareRoot(r0, Heap::kUndefinedValueRootIndex); 4593f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ b(eq, if_true); 4594e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(r0, if_false); 459580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for undetectable objects => true. 459680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); 459780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); 4598e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ tst(r1, Operand(1 << Map::kIsUndetectable)); 4599e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Split(ne, if_true, if_false, fall_through); 4600e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->function_string())) { 4602e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(r0, if_false); 46033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); 46043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareObjectType(r0, r0, r1, JS_FUNCTION_TYPE); 46053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(eq, if_true); 46063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r1, Operand(JS_FUNCTION_PROXY_TYPE)); 46073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Split(eq, if_true, if_false, fall_through); 4608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->object_string())) { 4609e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(r0, if_false); 4610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(r0, Heap::kNullValueRootIndex); 4611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(eq, if_true); 461280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for JS objects => true. 46133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CompareObjectType(r0, r0, r1, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); 46143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ b(lt, if_false); 46153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CompareInstanceType(r0, r1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); 46163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ b(gt, if_false); 4617e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Check for undetectable objects => false. 4618e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); 4619e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ tst(r1, Operand(1 << Map::kIsUndetectable)); 4620e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Split(eq, if_true, if_false, fall_through); 462180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 462280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (if_false != fall_through) __ jmp(if_false); 4623f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 46243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(if_true, if_false); 4625f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 4626f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 4627f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 4628d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 4629d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CompareOperation"); 463080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen SetSourcePosition(expr->position()); 4631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 46323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // First we try a fast inlined version of the compare when one of 46333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the operands is a literal. 46343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (TryLiteralCompare(expr)) return; 46353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4636e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Always perform the comparison for its control flow. Pack the result 4637e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // into the expression's context after the comparison is performed. 4638f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 4639f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 4640f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 464180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 46420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 46430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 464480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 46453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Token::Value op = expr->op(); 46460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->left()); 464780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen switch (op) { 4648e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Token::IN: 46490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->right()); 4650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 46513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); 4652d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ LoadRoot(ip, Heap::kTrueValueRootIndex); 4653d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmp(r0, ip); 465480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 4655d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 4656d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4657d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::INSTANCEOF: { 46580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->right()); 4659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstanceofStub stub(isolate(), InstanceofStub::kNoFlags); 4660d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 46613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 466280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // The stub returns 0 for true. 4663d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ tst(r0, r0); 466480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 4665d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 4666d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 4667d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4668d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: { 46690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->right()); 4670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond = CompareIC::ComputeCondition(op); 46713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(r1); 4672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 46730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool inline_smi_code = ShouldInlineSmiCase(op); 46741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block JumpPatchSite patch_site(masm_); 46750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (inline_smi_code) { 467680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label slow_case; 467780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ orr(r2, r0, Operand(r1)); 46781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block patch_site.EmitJumpIfNotSmi(r2, &slow_case); 467980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r1, r0); 46801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Split(cond, if_true, if_false, NULL); 468180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&slow_case); 468280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 46831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 46841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Record position and call the compare IC. 46851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block SetSourcePosition(expr->position()); 4686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code(); 4687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, expr->CompareOperationFeedbackId()); 46883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 46893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r0, Operand::Zero()); 46911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Split(cond, if_true, if_false, fall_through); 46923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 46933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 46943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4695e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Convert the result of the comparison into one expected for this 4696e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // expression's context. 46970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 4698e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 46993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4700d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 47013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, 47023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Expression* sub_expr, 47033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch NilValue nil) { 470480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label materialize_true, materialize_false; 470580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true = NULL; 470680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false = NULL; 470780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 47080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 47090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 471080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 47113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForAccumulatorValue(sub_expr); 47123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 47133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (expr->op() == Token::EQ_STRICT) { 4714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::RootListIndex nil_value = nil == kNullValue ? 4715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::kNullValueRootIndex : 4716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::kUndefinedValueRootIndex; 4717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(r1, nil_value); 471880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ cmp(r0, r1); 471980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(eq, if_true, if_false, fall_through); 4720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); 4722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, expr->CompareOperationFeedbackId()); 4723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r0, Operand(0)); 4724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(ne, if_true, if_false, fall_through); 472580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 47260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 472780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 472880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 472980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 4730d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { 4731e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 47320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(r0); 4733e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 4734d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 47360d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::result_register() { 47370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen return r0; 47380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4739d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4740e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 47410d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::context_register() { 47420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen return cp; 47430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 47440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 47450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4746d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 4747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); 4748e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ str(value, MemOperand(fp, frame_offset)); 4749d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 47503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4751e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4752d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) { 475359151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(dst, ContextOperand(cp, context_index)); 47543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 47553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4756d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 47573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::PushFunctionArgumentForContextAllocation() { 47583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Scope* declaration_scope = scope()->DeclarationScope(); 4759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (declaration_scope->is_global_scope() || 4760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch declaration_scope->is_module_scope()) { 4761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Contexts nested in the native context have a canonical empty function 47623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // as their closure, not the anonymous closure containing the global 47633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // code. Pass a smi sentinel and let the runtime look up the empty 47643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // function. 47653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(ip, Operand(Smi::FromInt(0))); 47663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else if (declaration_scope->is_eval_scope()) { 47673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Contexts created by a call to eval have the same closure as the 47683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // context calling eval, not the anonymous closure containing the eval 47693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // code. Fetch it from the context. 47703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ldr(ip, ContextOperand(cp, Context::CLOSURE_INDEX)); 47713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 4772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(declaration_scope->is_function_scope()); 47733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ldr(ip, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 47743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 47753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ push(ip); 47763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 47773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 47783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4779e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ---------------------------------------------------------------------------- 4780e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support. 4781e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4782d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() { 4783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!result_register().is(r1)); 4784e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store result register while executing finally block. 4785e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(result_register()); 4786e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Cook return address in link register to stack (smi encoded Code* delta) 4787e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ sub(r1, lr, Operand(masm_->CodeObject())); 4788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(r1); 4789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store result register while executing finally block. 4791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r1); 4792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store pending message while executing finally block. 4794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference pending_message_obj = 4795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_pending_message_obj(isolate()); 4796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ip, Operand(pending_message_obj)); 4797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r1, MemOperand(ip)); 4798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r1); 4799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference has_pending_message = 4801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_has_pending_message(isolate()); 4802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ip, Operand(has_pending_message)); 4803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(sizeof(bool) == 1); // NOLINT(runtime/sizeof) 4804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldrb(r1, MemOperand(ip)); 4805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(r1); 4806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r1); 4807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference pending_message_script = 4809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_pending_message_script(isolate()); 4810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ip, Operand(pending_message_script)); 4811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r1, MemOperand(ip)); 4812e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(r1); 4813e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 4814e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4815e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4816d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() { 4817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!result_register().is(r1)); 4818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore pending message from stack. 4819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(r1); 4820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference pending_message_script = 4821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_pending_message_script(isolate()); 4822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ip, Operand(pending_message_script)); 4823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r1, MemOperand(ip)); 4824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(r1); 4826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(r1); 4827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference has_pending_message = 4828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_has_pending_message(isolate()); 4829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ip, Operand(has_pending_message)); 4830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(sizeof(bool) == 1); // NOLINT(runtime/sizeof) 4831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ strb(r1, MemOperand(ip)); 4832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(r1); 4834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference pending_message_obj = 4835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_pending_message_obj(isolate()); 4836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ip, Operand(pending_message_obj)); 4837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r1, MemOperand(ip)); 4838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4839e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Restore result register from stack. 4840e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(r1); 4841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4842e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Uncook return address and return. 4843e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(result_register()); 4844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(r1); 4845e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ add(pc, r1, Operand(masm_->CodeObject())); 4846e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 4847e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4849e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#undef __ 4850d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 485169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#define __ ACCESS_MASM(masm()) 485269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 485369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochFullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit( 485469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int* stack_depth, 485569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int* context_length) { 485669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // The macros used here must preserve the result register. 485769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 485869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Because the handler block contains the context of the finally 485969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // code, we can restore it directly from there for the finally code 486069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // rather than iteratively unwinding contexts via their previous 486169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // links. 486269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Drop(*stack_depth); // Down to the handler block. 486369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (*context_length > 0) { 486469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Restore the context to its dedicated register and the stack. 486569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ ldr(cp, MemOperand(sp, StackHandlerConstants::kContextOffset)); 486669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 486769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 486869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ PopTryHandler(); 486969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bl(finally_entry_); 487069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 487169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch *stack_depth = 0; 487269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch *context_length = 0; 487369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch return previous_; 487469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch} 487569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 487669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 487769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#undef __ 487869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 4879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic Address GetInterruptImmediateLoadAddress(Address pc) { 4881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address load_address = pc - 2 * Assembler::kInstrSize; 4882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!FLAG_enable_ool_constant_pool) { 4883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(load_address))); 4884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (Assembler::IsLdrPpRegOffset(Memory::int32_at(load_address))) { 4885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This is an extended constant pool lookup. 4886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (CpuFeatures::IsSupported(ARMv7)) { 4887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch load_address -= 2 * Assembler::kInstrSize; 4888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsMovW(Memory::int32_at(load_address))); 4889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsMovT( 4890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Memory::int32_at(load_address + Assembler::kInstrSize))); 4891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch load_address -= 4 * Assembler::kInstrSize; 4893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsMovImmed(Memory::int32_at(load_address))); 4894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsOrrImmed( 4895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Memory::int32_at(load_address + Assembler::kInstrSize))); 4896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsOrrImmed( 4897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Memory::int32_at(load_address + 2 * Assembler::kInstrSize))); 4898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsOrrImmed( 4899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Memory::int32_at(load_address + 3 * Assembler::kInstrSize))); 4900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (CpuFeatures::IsSupported(ARMv7) && 4902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::IsMovT(Memory::int32_at(load_address))) { 4903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This is a movw / movt immediate load. 4904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch load_address -= Assembler::kInstrSize; 4905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsMovW(Memory::int32_at(load_address))); 4906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (!CpuFeatures::IsSupported(ARMv7) && 4907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::IsOrrImmed(Memory::int32_at(load_address))) { 4908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This is a mov / orr immediate load. 4909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch load_address -= 3 * Assembler::kInstrSize; 4910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsMovImmed(Memory::int32_at(load_address))); 4911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsOrrImmed( 4912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Memory::int32_at(load_address + Assembler::kInstrSize))); 4913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsOrrImmed( 4914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Memory::int32_at(load_address + 2 * Assembler::kInstrSize))); 4915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This is a small constant pool lookup. 4917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsLdrPpImmediateOffset(Memory::int32_at(load_address))); 4918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return load_address; 4920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid BackEdgeTable::PatchAt(Code* unoptimized_code, 4924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address pc, 4925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BackEdgeState target_state, 4926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code* replacement_code) { 4927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address pc_immediate_load_address = GetInterruptImmediateLoadAddress(pc); 4928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address branch_address = pc_immediate_load_address - Assembler::kInstrSize; 4929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodePatcher patcher(branch_address, 1); 4930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (target_state) { 4931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case INTERRUPT: 4932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 4933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // <decrement profiling counter> 4934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bpl ok 4935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ; load interrupt stub address into ip - either of (for ARMv7): 4936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ; <small cp load> | <extended cp load> | <immediate load> 4937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ldr ip, [pc/pp, #imm] | movw ip, #imm | movw ip, #imm 4938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // | movt ip, #imm | movw ip, #imm 4939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // | ldr ip, [pp, ip] 4940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ; or (for ARMv6): 4941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ; <small cp load> | <extended cp load> | <immediate load> 4942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ldr ip, [pc/pp, #imm] | mov ip, #imm | mov ip, #imm 4943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // | orr ip, ip, #imm> | orr ip, ip, #imm 4944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // | orr ip, ip, #imm> | orr ip, ip, #imm 4945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // | orr ip, ip, #imm> | orr ip, ip, #imm 4946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // blx ip 4947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // <reset profiling counter> 4948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ok-label 4949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Calculate branch offset to the ok-label - this is the difference 4951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // between the branch address and |pc| (which points at <blx ip>) plus 4952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // kProfileCounterResetSequence instructions 4953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int branch_offset = pc - Instruction::kPCReadOffset - branch_address + 4954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kProfileCounterResetSequenceLength; 4955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patcher.masm()->b(branch_offset, pl); 4956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case ON_STACK_REPLACEMENT: 4959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case OSR_AFTER_STACK_CHECK: 4960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // <decrement profiling counter> 4961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // mov r0, r0 (NOP) 4962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ; load on-stack replacement address into ip - either of (for ARMv7): 4963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ; <small cp load> | <extended cp load> | <immediate load> 4964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ldr ip, [pc/pp, #imm] | movw ip, #imm | movw ip, #imm 4965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // | movt ip, #imm> | movw ip, #imm 4966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // | ldr ip, [pp, ip] 4967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ; or (for ARMv6): 4968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ; <small cp load> | <extended cp load> | <immediate load> 4969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ldr ip, [pc/pp, #imm] | mov ip, #imm | mov ip, #imm 4970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // | orr ip, ip, #imm> | orr ip, ip, #imm 4971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // | orr ip, ip, #imm> | orr ip, ip, #imm 4972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // | orr ip, ip, #imm> | orr ip, ip, #imm 4973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // blx ip 4974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // <reset profiling counter> 4975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ok-label 4976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patcher.masm()->nop(); 4977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Replace the call address. 4981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::set_target_address_at(pc_immediate_load_address, unoptimized_code, 4982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch replacement_code->entry()); 4983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch( 4985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unoptimized_code, pc_immediate_load_address, replacement_code); 4986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochBackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState( 4990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate, 4991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code* unoptimized_code, 4992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address pc) { 4993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsBlxIp(Memory::int32_at(pc - Assembler::kInstrSize))); 4994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address pc_immediate_load_address = GetInterruptImmediateLoadAddress(pc); 4996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address branch_address = pc_immediate_load_address - Assembler::kInstrSize; 4997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address interrupt_address = Assembler::target_address_at( 4998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch pc_immediate_load_address, unoptimized_code); 4999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (Assembler::IsBranch(Assembler::instr_at(branch_address))) { 5001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(interrupt_address == 5002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate->builtins()->InterruptCheck()->entry()); 5003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return INTERRUPT; 5004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsNop(Assembler::instr_at(branch_address))); 5007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (interrupt_address == 5009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate->builtins()->OnStackReplacement()->entry()) { 5010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return ON_STACK_REPLACEMENT; 5011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(interrupt_address == 5014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate->builtins()->OsrAfterStackCheck()->entry()); 5015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return OSR_AFTER_STACK_CHECK; 5016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 50193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} } // namespace v8::internal 5020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 5021f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_ARM 5022