1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2014 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/ic/call-optimization.h" 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/handler-compiler.h" 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/ic.h" 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ ACCESS_MASM(masm) 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadViaGetter( 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Handle<HeapType> type, Register receiver, 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSFunction> getter) { 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------- S t a t e ------------- 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- r0 : receiver 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- r2 : name 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- lr : return address 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------------------------------- 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!getter.is_null()) { 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the JavaScript getter with the receiver on the stack. 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Swap in the global receiver. 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(receiver, 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(receiver); 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ParameterCount actual(0); 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ParameterCount expected(getter); 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeFunction(getter, expected, actual, CALL_FUNCTION, 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NullCallWrapper()); 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we generate a global code snippet for deoptimization only, remember 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the place to continue after deoptimization. 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore context register. 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedStoreHandlerCompiler::GenerateStoreViaSetter( 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Handle<HeapType> type, Register receiver, 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSFunction> setter) { 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------- S t a t e ------------- 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- lr : return address 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------------------------------- 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save value register, so we can restore it later. 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(value()); 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!setter.is_null()) { 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the JavaScript setter with receiver and value on the stack. 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Swap in the global receiver. 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(receiver, 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(receiver, value()); 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ParameterCount actual(1); 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ParameterCount expected(setter); 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeFunction(setter, expected, actual, CALL_FUNCTION, 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NullCallWrapper()); 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we generate a global code snippet for deoptimization only, remember 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the place to continue after deoptimization. 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset()); 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We have to return the passed value, not the return value of the setter. 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(r0); 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore context register. 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Label* miss_label, Register receiver, 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name, Register scratch0, Register scratch1) { 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(name->IsUniqueName()); 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!receiver.is(scratch0)); 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Counters* counters = masm->isolate()->counters(); 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kInterceptorOrAccessCheckNeededMask = 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Bail out if the receiver has a named interceptor or requires access checks. 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register map = scratch1; 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldrb(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ tst(scratch0, Operand(kInterceptorOrAccessCheckNeededMask)); 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, miss_label); 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that receiver is a JSObject. 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldrb(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(scratch0, Operand(FIRST_SPEC_OBJECT_TYPE)); 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(lt, miss_label); 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load properties array. 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register properties = scratch0; 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the properties array is a dictionary. 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(map, FieldMemOperand(properties, HeapObject::kMapOffset)); 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register tmp = properties; 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(map, tmp); 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, miss_label); 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore the temporarily used register. 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionaryLookupStub::GenerateNegativeLookup( 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm, miss_label, &done, receiver, properties, name, scratch1); 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype( 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, int index, Register prototype, Label* miss) { 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate = masm->isolate(); 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the global function with the given index. 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSFunction> function( 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSFunction::cast(isolate->native_context()->get(index))); 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check we're still in the same context. 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch = prototype; 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(scratch, MemOperand(cp, offset)); 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset)); 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(scratch, MemOperand(scratch, Context::SlotOffset(index))); 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(ip, function); 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(ip, scratch); 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, miss); 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load its initial map. The global functions all have initial maps. 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(prototype, Handle<Map>(function->initial_map())); 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the prototype from the initial map. 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype( 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Register receiver, Register scratch1, 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2, Label* miss_label) { 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r0, scratch1); 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Generate code to check that a global property cell is empty. Create 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// the property cell at compilation time if no cell exists for the 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// property. 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PropertyHandlerCompiler::GenerateCheckPropertyCell( 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, Label* miss) { 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Cell> cell = JSGlobalObject::EnsurePropertyCell(global, name); 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(cell->value()->IsTheHole()); 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch, Operand(cell)); 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(scratch, ip); 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, miss); 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void PushInterceptorArguments(MacroAssembler* masm, Register receiver, 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register holder, Register name, 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> holder_obj) { 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1); 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2); 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3); 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 4); 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(name); 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!masm->isolate()->heap()->InNewSpace(*interceptor)); 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch = name; 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch, Operand(interceptor)); 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(scratch); 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(receiver); 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(holder); 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CompileCallLoadPropertyWithInterceptor( 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Register receiver, Register holder, Register name, 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> holder_obj, IC::UtilityId id) { 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PushInterceptorArguments(masm, receiver, holder, name, holder_obj); 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallExternalReference(ExternalReference(IC_Utility(id), masm->isolate()), 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NamedLoadHandlerCompiler::kInterceptorArgsLength); 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Generate call to api function. 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PropertyHandlerCompiler::GenerateFastApiCall( 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, const CallOptimization& optimization, 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> receiver_map, Register receiver, Register scratch_in, 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_store, int argc, Register* values) { 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!receiver.is(scratch_in)); 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(receiver); 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Write the arguments to stack frame. 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < argc; i++) { 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register arg = values[argc - 1 - i]; 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!receiver.is(arg)); 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch_in.is(arg)); 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(arg); 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(optimization.is_simple_api_call()); 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Abi for CallApiFunctionStub. 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register callee = r0; 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register call_data = r4; 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register holder = r2; 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register api_function_address = r1; 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Put holder in place. 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallOptimization::HolderLookup holder_lookup; 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> api_holder = 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch optimization.LookupHolderOfExpectedType(receiver_map, &holder_lookup); 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (holder_lookup) { 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CallOptimization::kHolderIsReceiver: 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(holder, receiver); 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CallOptimization::kHolderFound: 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(holder, api_holder); 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CallOptimization::kHolderNotFound: 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate = masm->isolate(); 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSFunction> function = optimization.constant_function(); 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> call_data_obj(api_call_info->data(), isolate); 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Put callee in place. 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(callee, function); 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool call_data_undefined = false; 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Put call_data in place. 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (isolate->heap()->InNewSpace(*call_data_obj)) { 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(call_data, api_call_info); 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(call_data, FieldMemOperand(call_data, CallHandlerInfo::kDataOffset)); 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (call_data_obj->IsUndefined()) { 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch call_data_undefined = true; 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(call_data, Heap::kUndefinedValueRootIndex); 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(call_data, call_data_obj); 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Put api_function_address in place. 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address function_address = v8::ToCData<Address>(api_call_info->callback()); 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ApiFunction fun(function_address); 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::Type type = ExternalReference::DIRECT_API_CALL; 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference ref = ExternalReference(&fun, type, masm->isolate()); 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(api_function_address, Operand(ref)); 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Jump to stub. 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc); 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallStub(&stub); 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedStoreHandlerCompiler::GenerateSlow(MacroAssembler* masm) { 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push receiver, key and value for runtime call. 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(), 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StoreDescriptor::ValueRegister()); 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The slow case calls into the runtime to complete the store without causing 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // an IC miss that would otherwise cause a transition to the generic stub. 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference ref = 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference(IC_Utility(IC::kStoreIC_Slow), masm->isolate()); 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallExternalReference(ref, 3, 1); 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) { 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push receiver, key and value for runtime call. 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(), 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StoreDescriptor::ValueRegister()); 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The slow case calls into the runtime to complete the store without causing 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // an IC miss that would otherwise cause a transition to the generic stub. 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference ref = 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference(IC_Utility(IC::kKeyedStoreIC_Slow), masm->isolate()); 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallExternalReference(ref, 3, 1); 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __ 317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ ACCESS_MASM(masm()) 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name) { 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!label->is_unused()) { 323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(label); 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(this->name(), Operand(name)); 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Generate StoreTransition code, value is passed in r0 register. 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// When leaving generated code after success, the receiver_reg and name_reg 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// may be clobbered. Upon branch to miss_label, the receiver and name 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// registers have their original values. 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedStoreHandlerCompiler::GenerateStoreTransition( 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> transition, Handle<Name> name, Register receiver_reg, 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register storage_reg, Register value_reg, Register scratch1, 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2, Register scratch3, Label* miss_label, Label* slow) { 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r0 : value 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label exit; 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int descriptor = transition->LastAdded(); 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DescriptorArray* descriptors = transition->instance_descriptors(); 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PropertyDetails details = descriptors->GetDetails(descriptor); 343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Representation representation = details.representation(); 344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!representation.IsNone()); 345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (details.type() == CONSTANT) { 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> constant(descriptors->GetValue(descriptor), isolate()); 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(scratch1, constant); 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(value_reg, scratch1); 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, miss_label); 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (representation.IsSmi()) { 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotSmi(value_reg, miss_label); 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (representation.IsHeapObject()) { 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(value_reg, miss_label); 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapType* field_type = descriptors->GetFieldType(descriptor); 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapType::Iterator<Map> it = field_type->Classes(); 357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!it.Done()) { 358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset)); 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label do_store; 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (true) { 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareMap(scratch1, it.Current(), &do_store); 362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch it.Advance(); 363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (it.Done()) { 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, miss_label); 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(eq, &do_store); 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&do_store); 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (representation.IsDouble()) { 372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label do_store, heap_number; 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(scratch3, Heap::kMutableHeapNumberMapRootIndex); 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AllocateHeapNumber(storage_reg, scratch1, scratch2, scratch3, slow, 375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TAG_RESULT, MUTABLE); 376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotSmi(value_reg, &heap_number); 378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(scratch1, value_reg); 379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vmov(s0, scratch1); 380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vcvt_f64_s32(d0, s0); 381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&do_store); 382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&heap_number); 384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, miss_label, 385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DONT_DO_SMI_CHECK); 386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vldr(d0, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); 387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&do_store); 389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vstr(d0, FieldMemOperand(storage_reg, HeapNumber::kValueOffset)); 390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Stub never generated for objects that require access checks. 393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!transition->is_access_check_needed()); 394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform map transition for the receiver if necessary. 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (details.type() == FIELD && 397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { 398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The properties must be extended before we can store the value. 399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We jump to a runtime call that extends the properties array. 400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(receiver_reg); 401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r2, Operand(transition)); 402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(r2, r0); 403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallExternalReference( 404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), 405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate()), 406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3, 1); 407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update the map of the object. 411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch1, Operand(transition)); 412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(scratch1, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); 413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update the write barrier for the map field. 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteField(receiver_reg, HeapObject::kMapOffset, scratch1, scratch2, 416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kLRHasNotBeenSaved, kDontSaveFPRegs, OMIT_REMEMBERED_SET, 417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OMIT_SMI_CHECK); 418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (details.type() == CONSTANT) { 420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(value_reg.is(r0)); 421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int index = transition->instance_descriptors()->GetFieldIndex( 426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch transition->LastAdded()); 427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Adjust for the number of properties stored in the object. Even in the 429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // face of a transition we can use the old map here because the size of the 430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // object and the number of in-object properties is not going to change. 431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch index -= transition->inobject_properties(); 432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(verwaest): Share this code as a code stub. 434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SmiCheck smi_check = 435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch representation.IsTagged() ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; 436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (index < 0) { 437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Set the property straight into the object. 438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = transition->instance_size() + (index * kPointerSize); 439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (representation.IsDouble()) { 440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(storage_reg, FieldMemOperand(receiver_reg, offset)); 441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(value_reg, FieldMemOperand(receiver_reg, offset)); 443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!representation.IsSmi()) { 446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update the write barrier for the array address. 447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!representation.IsDouble()) { 448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(storage_reg, value_reg); 449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteField(receiver_reg, offset, storage_reg, scratch1, 451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kLRHasNotBeenSaved, kDontSaveFPRegs, 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EMIT_REMEMBERED_SET, smi_check); 453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Write to the properties array. 456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = index * kPointerSize + FixedArray::kHeaderSize; 457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the properties array 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(scratch1, 459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (representation.IsDouble()) { 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(storage_reg, FieldMemOperand(scratch1, offset)); 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(value_reg, FieldMemOperand(scratch1, offset)); 464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!representation.IsSmi()) { 467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update the write barrier for the array address. 468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!representation.IsDouble()) { 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(storage_reg, value_reg); 470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteField(scratch1, offset, storage_reg, receiver_reg, 472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kLRHasNotBeenSaved, kDontSaveFPRegs, 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EMIT_REMEMBERED_SET, smi_check); 474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the value (register r0). 478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(value_reg.is(r0)); 479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&exit); 480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedStoreHandlerCompiler::GenerateStoreField(LookupIterator* lookup, 485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value_reg, 486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* miss_label) { 487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(lookup->representation().IsHeapObject()); 488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(value_reg, miss_label); 489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapType::Iterator<Map> it = lookup->GetFieldType()->Classes(); 490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(scratch1(), FieldMemOperand(value_reg, HeapObject::kMapOffset)); 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label do_store; 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (true) { 493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareMap(scratch1(), it.Current(), &do_store); 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch it.Advance(); 495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (it.Done()) { 496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, miss_label); 497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(eq, &do_store); 500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&do_store); 502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StoreFieldStub stub(isolate(), lookup->GetFieldIndex(), 504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch lookup->representation()); 505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateTailCall(masm(), stub.GetCode()); 506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister PropertyHandlerCompiler::CheckPrototypes( 510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object_reg, Register holder_reg, Register scratch1, 511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2, Handle<Name> name, Label* miss, 512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrototypeCheckType check) { 513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); 514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Make sure there's no overlap between holder and object registers. 516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && 518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !scratch2.is(scratch1)); 519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Keep track of the current object in register reg. 521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg = object_reg; 522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int depth = 0; 523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> current = Handle<JSObject>::null(); 525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (type()->IsConstant()) { 526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch current = Handle<JSObject>::cast(type()->AsConstant()->Value()); 527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> prototype = Handle<JSObject>::null(); 529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> current_map = receiver_map; 530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> holder_map(holder()->map()); 531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Traverse the prototype chain and check the maps in the prototype chain for 532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // fast and global objects or do negative lookup for normal objects. 533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (!current_map.is_identical_to(holder_map)) { 534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++depth; 535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Only global objects and objects that do not require access 537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // checks are allowed in stubs. 538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(current_map->IsJSGlobalProxyMap() || 539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !current_map->is_access_check_needed()); 540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch prototype = handle(JSObject::cast(current_map->prototype())); 542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (current_map->is_dictionary_map() && 543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !current_map->IsJSGlobalObjectMap()) { 544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. 545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!name->IsUniqueName()) { 546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(name->IsString()); 547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name = factory()->InternalizeString(Handle<String>::cast(name)); 548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(current.is_null() || 550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch current->property_dictionary()->FindEntry(name) == 551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionary::kNotFound); 552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, 554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scratch2); 555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); 557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg = holder_reg; // From now on the object will be in holder_reg. 558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); 559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register map_reg = scratch1; 561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (depth != 1 || check == CHECK_ALL_MAPS) { 562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // CheckMap implicitly loads the map of |reg| into |map_reg|. 563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CheckMap(reg, map_reg, current_map, miss, DONT_DO_SMI_CHECK); 564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); 566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check access rights to the global object. This has to happen after 569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the map check so that we know that the object is actually a global 570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // object. 571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This allows us to install generated handlers for accesses to the 572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // global proxy (as opposed to using slow ICs). See corresponding code 573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // in LookupForRead(). 574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (current_map->IsJSGlobalProxyMap()) { 575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CheckAccessGlobalProxy(reg, scratch2, miss); 576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (current_map->IsJSGlobalObjectMap()) { 577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), 578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name, scratch2, miss); 579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg = holder_reg; // From now on the object will be in holder_reg. 582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Two possible reasons for loading the prototype from the map: 584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (1) Can't store references to new space in code. 585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (2) Handler is shared for all receivers with the same prototype 586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // map (but not necessarily the same prototype instance). 587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool load_prototype_from_map = 588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap()->InNewSpace(*prototype) || depth == 1; 589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (load_prototype_from_map) { 590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); 591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(reg, Operand(prototype)); 593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Go to the next object in the prototype chain. 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch current = prototype; 598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch current_map = handle(current->map()); 599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Log the check depth. 602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); 603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (depth != 0 || check == CHECK_ALL_MAPS) { 605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check the holder map. 606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK); 607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform security check for access to the global object. 610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(current_map->IsJSGlobalProxyMap() || 611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !current_map->is_access_check_needed()); 612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (current_map->IsJSGlobalProxyMap()) { 613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CheckAccessGlobalProxy(reg, scratch1, miss); 614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the register containing the holder. 617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return reg; 618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { 622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!miss->is_unused()) { 623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label success; 624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(&success); 625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(miss); 626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TailCallBuiltin(masm(), MissBuiltin(kind())); 627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&success); 628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { 633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!miss->is_unused()) { 634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label success; 635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(&success); 636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateRestoreName(miss, name); 637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TailCallBuiltin(masm(), MissBuiltin(kind())); 638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&success); 639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { 644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the constant value. 645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(r0, value); 646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadCallback( 651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg, Handle<ExecutableAccessorInfo> callback) { 652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Build AccessorInfo::args_ list on the stack and push property name below 653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the exit frame to make GC aware of them and store pointers to them. 654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); 655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); 656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); 657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); 658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); 659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); 660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6); 661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch2().is(reg)); 662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch3().is(reg)); 663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch4().is(reg)); 664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(receiver()); 665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (heap()->InNewSpace(callback->data())) { 666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(scratch3(), callback); 667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(scratch3(), 668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldMemOperand(scratch3(), ExecutableAccessorInfo::kDataOffset)); 669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(scratch3(), Handle<Object>(callback->data(), isolate())); 671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(scratch3()); 673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(scratch3(), Heap::kUndefinedValueRootIndex); 674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch4(), scratch3()); 675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(scratch3(), scratch4()); 676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch4(), Operand(ExternalReference::isolate_address(isolate()))); 677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(scratch4(), reg); 678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch2(), sp); // scratch2 = PropertyAccessorInfo::args_ 679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(name()); 680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Abi for CallApiGetter 682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register getter_address_reg = ApiGetterDescriptor::function_address(); 683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address getter_address = v8::ToCData<Address>(callback->getter()); 685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ApiFunction fun(getter_address); 686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; 687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference ref = ExternalReference(&fun, type, isolate()); 688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(getter_address_reg, Operand(ref)); 689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallApiGetterStub stub(isolate()); 691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallStub(&stub); 692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup( 696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LookupIterator* it, Register holder_reg) { 697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(holder()->HasNamedInterceptor()); 698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); 699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compile the interceptor call, followed by inline code to load the 701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // property from further up the prototype chain if the call fails. 702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the maps haven't changed. 703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1())); 704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Preserve the receiver register explicitly whenever it is different from the 706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // holder and it is needed should the interceptor return without any result. 707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The ACCESSOR case needs the receiver to be passed into C++ code, the FIELD 708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // case might cause a miss during the prototype check. 709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool must_perform_prototype_check = 710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !holder().is_identical_to(it->GetHolder<JSObject>()); 711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool must_preserve_receiver_reg = 712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !receiver().is(holder_reg) && 713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (it->state() == LookupIterator::ACCESSOR || must_perform_prototype_check); 714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save necessary data before invoking an interceptor. 716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Requires a frame to make GC aware of pushed pointers. 717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameAndConstantPoolScope frame_scope(masm(), StackFrame::INTERNAL); 719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (must_preserve_receiver_reg) { 720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(receiver(), holder_reg, this->name()); 721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(holder_reg, this->name()); 723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Invoke an interceptor. Note: map checks from receiver to 725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // interceptor's holder has been compiled before (see a caller 726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of this method.) 727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CompileCallLoadPropertyWithInterceptor( 728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm(), receiver(), holder_reg, this->name(), holder(), 729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IC::kLoadPropertyWithInterceptorOnly); 730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if interceptor provided a value for property. If it's 732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the case, return immediately. 733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label interceptor_failed; 734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex); 735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r0, scratch1()); 736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(eq, &interceptor_failed); 737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch frame_scope.GenerateLeaveFrame(); 738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&interceptor_failed); 741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(this->name()); 742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(holder_reg); 743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (must_preserve_receiver_reg) { 744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(receiver()); 745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Leave the internal frame. 747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateLoadPostInterceptor(it, holder_reg); 750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) { 754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the runtime system to load the interceptor. 755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(holder()->HasNamedInterceptor()); 756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); 757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(), 758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch holder()); 759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference ref = ExternalReference( 761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IC_Utility(IC::kLoadPropertyWithInterceptor), isolate()); 762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallExternalReference( 763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); 764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( 768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> object, Handle<Name> name, 769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<ExecutableAccessorInfo> callback) { 770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register holder_reg = Frontend(receiver(), name); 771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(receiver()); // receiver 773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(holder_reg); 774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ip, Operand(callback)); // callback info 775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(ip); 776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ip, Operand(name)); 777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(ip, value()); 778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do tail-call to the runtime system. 780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference store_callback_property = 781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); 782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallExternalReference(store_callback_property, 5, 1); 783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the generated code. 785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return GetCode(kind(), Code::FAST, name); 786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( 790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name) { 791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(receiver(), this->name(), value()); 792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do tail-call to the runtime system. 794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference store_ic_property = ExternalReference( 795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); 796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallExternalReference(store_ic_property, 3, 1); 797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the generated code. 799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return GetCode(kind(), Code::FAST, name); 800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister NamedStoreHandlerCompiler::value() { 804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return StoreDescriptor::ValueRegister(); 805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( 809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { 810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label miss; 811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrontendHeader(receiver(), name, &miss); 812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the value from the cell. 814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = StoreDescriptor::ValueRegister(); 815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, Operand(cell)); 816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(result, FieldMemOperand(result, Cell::kValueOffset)); 817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for deleted property if property can actually be deleted. 819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (is_configurable) { 820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(result, ip); 822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(eq, &miss); 823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Counters* counters = isolate()->counters(); 826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3); 827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrontendFooter(name, &miss); 830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the generated code. 832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return GetCode(kind(), Code::NORMAL, name); 833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __ 837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace v8::internal 839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // V8_TARGET_ARCH_ARM 841