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