handler-compiler-ppc.cc revision 958fae7ec3f466955f8e5b50fa5b8d38b9e91675
1958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Copyright 2014 the V8 project authors. All rights reserved. 2958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Use of this source code is governed by a BSD-style license that can be 3958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// found in the LICENSE file. 4958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/v8.h" 6958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 7958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#if V8_TARGET_ARCH_PPC 8958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 9958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/ic/call-optimization.h" 10958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/ic/handler-compiler.h" 11958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/ic/ic.h" 12958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 13958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace v8 { 14958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace internal { 15958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 16958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#define __ ACCESS_MASM(masm) 17958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 18958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 19958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::GenerateLoadViaGetter( 20958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, Handle<HeapType> type, Register receiver, 21958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<JSFunction> getter) { 22958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // ----------- S t a t e ------------- 23958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- r3 : receiver 24958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- r5 : name 25958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- lr : return address 26958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // ----------------------------------- 27958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier { 28958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 29958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 30958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!getter.is_null()) { 31958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Call the JavaScript getter with the receiver on the stack. 32958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { 33958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Swap in the global receiver. 34958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(receiver, 35958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); 36958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 37958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(receiver); 38958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ParameterCount actual(0); 39958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ParameterCount expected(getter); 40958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ InvokeFunction(getter, expected, actual, CALL_FUNCTION, 41958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NullCallWrapper()); 42958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 43958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If we generate a global code snippet for deoptimization only, remember 44958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the place to continue after deoptimization. 45958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); 46958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 47958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 48958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Restore context register. 49958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 50958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 51958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 52958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 53958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 54958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 55958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::GenerateStoreViaSetter( 56958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, Handle<HeapType> type, Register receiver, 57958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<JSFunction> setter) { 58958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // ----------- S t a t e ------------- 59958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- lr : return address 60958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // ----------------------------------- 61958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier { 62958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 63958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 64958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Save value register, so we can restore it later. 65958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(value()); 66958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 67958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!setter.is_null()) { 68958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Call the JavaScript setter with receiver and value on the stack. 69958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { 70958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Swap in the global receiver. 71958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(receiver, 72958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); 73958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 74958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(receiver, value()); 75958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ParameterCount actual(1); 76958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ParameterCount expected(setter); 77958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ InvokeFunction(setter, expected, actual, CALL_FUNCTION, 78958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NullCallWrapper()); 79958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 80958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If we generate a global code snippet for deoptimization only, remember 81958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the place to continue after deoptimization. 82958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset()); 83958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 84958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 85958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // We have to return the passed value, not the return value of the setter. 86958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ pop(r3); 87958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 88958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Restore context register. 89958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 90958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 91958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 92958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 93958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 94958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 95958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( 96958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, Label* miss_label, Register receiver, 97958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<Name> name, Register scratch0, Register scratch1) { 98958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(name->IsUniqueName()); 99958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!receiver.is(scratch0)); 100958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Counters* counters = masm->isolate()->counters(); 101958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); 102958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); 103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 104958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label done; 105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const int kInterceptorOrAccessCheckNeededMask = 107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); 108958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Bail out if the receiver has a named interceptor or requires access checks. 110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register map = scratch1; 111958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); 112958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); 113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, scratch0, Operand(kInterceptorOrAccessCheckNeededMask)); 114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(miss_label, cr0); 115958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 116958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that receiver is a JSObject. 117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); 118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmpi(scratch0, Operand(FIRST_SPEC_OBJECT_TYPE)); 119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ blt(miss_label); 120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load properties array. 122958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register properties = scratch0; 123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that the properties array is a dictionary. 125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(map, FieldMemOperand(properties, HeapObject::kMapOffset)); 126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register tmp = properties; 127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); 128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(map, tmp); 129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(miss_label); 130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Restore the temporarily used register. 132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NameDictionaryLookupStub::GenerateNegativeLookup( 136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier masm, miss_label, &done, receiver, properties, name, scratch1); 137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&done); 138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); 139958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype( 143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, int index, Register prototype, Label* miss) { 144958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Isolate* isolate = masm->isolate(); 145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Get the global function with the given index. 146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<JSFunction> function( 147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier JSFunction::cast(isolate->native_context()->get(index))); 148958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check we're still in the same context. 150958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch = prototype; 151958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); 152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(scratch, MemOperand(cp, offset)); 153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(scratch, 154958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldMemOperand(scratch, GlobalObject::kNativeContextOffset)); 155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(scratch, MemOperand(scratch, Context::SlotOffset(index))); 156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Move(ip, function); 157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(ip, scratch); 158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(miss); 159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 160958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load its initial map. The global functions all have initial maps. 161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Move(prototype, Handle<Map>(function->initial_map())); 162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load the prototype from the initial map. 163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); 164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 165958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 166958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 167958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype( 168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, Register receiver, Register scratch1, 169958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch2, Label* miss_label) { 170958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); 171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r3, scratch1); 172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 173958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 174958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 175958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 176958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Generate code to check that a global property cell is empty. Create 177958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// the property cell at compilation time if no cell exists for the 178958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// property. 179958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid PropertyHandlerCompiler::GenerateCheckPropertyCell( 180958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, 181958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch, Label* miss) { 182958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<Cell> cell = JSGlobalObject::EnsurePropertyCell(global, name); 183958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(cell->value()->IsTheHole()); 184958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(scratch, Operand(cell)); 185958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); 186958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 187958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(scratch, ip); 188958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(miss); 189958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 190958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 191958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 192958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void PushInterceptorArguments(MacroAssembler* masm, Register receiver, 193958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register holder, Register name, 194958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<JSObject> holder_obj) { 195958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); 196958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1); 197958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2); 198958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3); 199958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 4); 200958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(name); 201958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); 202958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!masm->isolate()->heap()->InNewSpace(*interceptor)); 203958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch = name; 204958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(scratch, Operand(interceptor)); 205958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(scratch); 206958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(receiver); 207958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(holder); 208958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 210958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 211958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void CompileCallLoadPropertyWithInterceptor( 212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, Register receiver, Register holder, Register name, 213958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<JSObject> holder_obj, IC::UtilityId id) { 214958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PushInterceptorArguments(masm, receiver, holder, name, holder_obj); 215958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CallExternalReference(ExternalReference(IC_Utility(id), masm->isolate()), 216958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NamedLoadHandlerCompiler::kInterceptorArgsLength); 217958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 218958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 219958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 220958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Generate call to api function. 221958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid PropertyHandlerCompiler::GenerateFastApiCall( 222958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, const CallOptimization& optimization, 223958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<Map> receiver_map, Register receiver, Register scratch_in, 224958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool is_store, int argc, Register* values) { 225958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!receiver.is(scratch_in)); 226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(receiver); 227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Write the arguments to stack frame. 228958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier for (int i = 0; i < argc; i++) { 229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register arg = values[argc - 1 - i]; 230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!receiver.is(arg)); 231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!scratch_in.is(arg)); 232958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(arg); 233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(optimization.is_simple_api_call()); 235958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 236958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Abi for CallApiFunctionStub. 237958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register callee = r3; 238958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register call_data = r7; 239958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register holder = r5; 240958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register api_function_address = r4; 241958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 242958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Put holder in place. 243958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CallOptimization::HolderLookup holder_lookup; 244958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<JSObject> api_holder = 245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier optimization.LookupHolderOfExpectedType(receiver_map, &holder_lookup); 246958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier switch (holder_lookup) { 247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case CallOptimization::kHolderIsReceiver: 248958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Move(holder, receiver); 249958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 250958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case CallOptimization::kHolderFound: 251958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Move(holder, api_holder); 252958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 253958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case CallOptimization::kHolderNotFound: 254958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier UNREACHABLE(); 255958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 256958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 257958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 258958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Isolate* isolate = masm->isolate(); 259958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<JSFunction> function = optimization.constant_function(); 260958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 261958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<Object> call_data_obj(api_call_info->data(), isolate); 262958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 263958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Put callee in place. 264958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Move(callee, function); 265958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 266958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool call_data_undefined = false; 267958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Put call_data in place. 268958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (isolate->heap()->InNewSpace(*call_data_obj)) { 269958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Move(call_data, api_call_info); 270958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(call_data, 271958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldMemOperand(call_data, CallHandlerInfo::kDataOffset)); 272958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (call_data_obj->IsUndefined()) { 273958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier call_data_undefined = true; 274958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(call_data, Heap::kUndefinedValueRootIndex); 275958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 276958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Move(call_data, call_data_obj); 277958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 278958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 279958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Put api_function_address in place. 280958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Address function_address = v8::ToCData<Address>(api_call_info->callback()); 281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ApiFunction fun(function_address); 282958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference::Type type = ExternalReference::DIRECT_API_CALL; 283958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference ref = ExternalReference(&fun, type, masm->isolate()); 284958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(api_function_address, Operand(ref)); 285958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 286958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Jump to stub. 287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc); 288958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ TailCallStub(&stub); 289958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 292958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::GenerateSlow(MacroAssembler* masm) { 293958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Push receiver, key and value for runtime call. 294958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(), 295958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StoreDescriptor::ValueRegister()); 296958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 297958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // The slow case calls into the runtime to complete the store without causing 298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // an IC miss that would otherwise cause a transition to the generic stub. 299958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference ref = 300958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference(IC_Utility(IC::kStoreIC_Slow), masm->isolate()); 301958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ TailCallExternalReference(ref, 3, 1); 302958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 303958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 304958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 305958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) { 306958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Push receiver, key and value for runtime call. 307958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(), 308958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StoreDescriptor::ValueRegister()); 309958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 310958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // The slow case calls into the runtime to complete the store without causing 311958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // an IC miss that would otherwise cause a transition to the generic stub. 312958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference ref = 313958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference(IC_Utility(IC::kKeyedStoreIC_Slow), masm->isolate()); 314958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ TailCallExternalReference(ref, 3, 1); 315958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 316958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 317958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 318958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#undef __ 319958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#define __ ACCESS_MASM(masm()) 320958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 321958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, 323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<Name> name) { 324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!label->is_unused()) { 325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(label); 326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(this->name(), Operand(name)); 327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::GenerateRestoreNameAndMap( 332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<Name> name, Handle<Map> transition) { 333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(this->name(), Operand(name)); 334958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(StoreTransitionDescriptor::MapRegister(), Operand(transition)); 335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::GenerateConstantCheck(Object* constant, 339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register value_reg, 340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label* miss_label) { 341958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Move(scratch1(), handle(constant, isolate())); 342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(value_reg, scratch1()); 343958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(miss_label); 344958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 345958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 346958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 347958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::GenerateFieldTypeChecks(HeapType* field_type, 348958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register value_reg, 349958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label* miss_label) { 350958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfSmi(value_reg, miss_label); 351958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier HeapType::Iterator<Map> it = field_type->Classes(); 352958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!it.Done()) { 353958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(scratch1(), FieldMemOperand(value_reg, HeapObject::kMapOffset)); 354958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label do_store; 355958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier while (true) { 356958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CompareMap(scratch1(), it.Current(), &do_store); 357958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier it.Advance(); 358958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (it.Done()) { 359958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(miss_label); 360958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 361958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 362958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&do_store); 363958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 364958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&do_store); 365958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 366958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 367958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 368958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 369958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRegister PropertyHandlerCompiler::CheckPrototypes( 370958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register object_reg, Register holder_reg, Register scratch1, 371958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch2, Handle<Name> name, Label* miss, 372958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PrototypeCheckType check) { 373958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); 374958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 375958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Make sure there's no overlap between holder and object registers. 376958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 377958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && 378958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier !scratch2.is(scratch1)); 379958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 380958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Keep track of the current object in register reg. 381958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register reg = object_reg; 382958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int depth = 0; 383958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 384958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<JSObject> current = Handle<JSObject>::null(); 385958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (type()->IsConstant()) { 386958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier current = Handle<JSObject>::cast(type()->AsConstant()->Value()); 387958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 388958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<JSObject> prototype = Handle<JSObject>::null(); 389958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<Map> current_map = receiver_map; 390958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<Map> holder_map(holder()->map()); 391958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Traverse the prototype chain and check the maps in the prototype chain for 392958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // fast and global objects or do negative lookup for normal objects. 393958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier while (!current_map.is_identical_to(holder_map)) { 394958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ++depth; 395958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 396958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Only global objects and objects that do not require access 397958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // checks are allowed in stubs. 398958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(current_map->IsJSGlobalProxyMap() || 399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier !current_map->is_access_check_needed()); 400958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 401958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier prototype = handle(JSObject::cast(current_map->prototype())); 402958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (current_map->is_dictionary_map() && 403958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier !current_map->IsJSGlobalObjectMap()) { 404958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. 405958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!name->IsUniqueName()) { 406958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(name->IsString()); 407958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier name = factory()->InternalizeString(Handle<String>::cast(name)); 408958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 409958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(current.is_null() || 410958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier current->property_dictionary()->FindEntry(name) == 411958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NameDictionary::kNotFound); 412958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, 414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier scratch2); 415958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 416958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); 417958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier reg = holder_reg; // From now on the object will be in holder_reg. 418958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); 419958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 420958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register map_reg = scratch1; 421958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (depth != 1 || check == CHECK_ALL_MAPS) { 422958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // CheckMap implicitly loads the map of |reg| into |map_reg|. 423958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CheckMap(reg, map_reg, current_map, miss, DONT_DO_SMI_CHECK); 424958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 425958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); 426958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 427958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 428958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check access rights to the global object. This has to happen after 429958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the map check so that we know that the object is actually a global 430958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // object. 431958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // This allows us to install generated handlers for accesses to the 432958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // global proxy (as opposed to using slow ICs). See corresponding code 433958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // in LookupForRead(). 434958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (current_map->IsJSGlobalProxyMap()) { 435958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CheckAccessGlobalProxy(reg, scratch2, miss); 436958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (current_map->IsJSGlobalObjectMap()) { 437958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), 438958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier name, scratch2, miss); 439958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 440958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 441958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier reg = holder_reg; // From now on the object will be in holder_reg. 442958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 443958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Two possible reasons for loading the prototype from the map: 444958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // (1) Can't store references to new space in code. 445958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // (2) Handler is shared for all receivers with the same prototype 446958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // map (but not necessarily the same prototype instance). 447958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool load_prototype_from_map = 448958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier heap()->InNewSpace(*prototype) || depth == 1; 449958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (load_prototype_from_map) { 450958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); 451958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 452958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(reg, Operand(prototype)); 453958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 454958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 455958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 456958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Go to the next object in the prototype chain. 457958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier current = prototype; 458958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier current_map = handle(current->map()); 459958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 460958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 461958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Log the check depth. 462958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); 463958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 464958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (depth != 0 || check == CHECK_ALL_MAPS) { 465958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check the holder map. 466958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK); 467958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 468958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 469958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Perform security check for access to the global object. 470958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(current_map->IsJSGlobalProxyMap() || 471958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier !current_map->is_access_check_needed()); 472958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (current_map->IsJSGlobalProxyMap()) { 473958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CheckAccessGlobalProxy(reg, scratch1, miss); 474958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 475958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 476958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Return the register containing the holder. 477958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return reg; 478958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 479958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 480958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 481958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { 482958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!miss->is_unused()) { 483958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label success; 484958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&success); 485958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(miss); 486958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier TailCallBuiltin(masm(), MissBuiltin(kind())); 487958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&success); 488958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 489958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 490958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 491958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 492958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { 493958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!miss->is_unused()) { 494958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label success; 495958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&success); 496958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateRestoreName(miss, name); 497958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier TailCallBuiltin(masm(), MissBuiltin(kind())); 498958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&success); 499958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 500958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 501958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 502958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 503958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { 504958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Return the constant value. 505958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Move(r3, value); 506958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 507958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 508958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 509958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 510958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::GenerateLoadCallback( 511958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register reg, Handle<ExecutableAccessorInfo> callback) { 512958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Build AccessorInfo::args_ list on the stack and push property name below 513958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the exit frame to make GC aware of them and store pointers to them. 514958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); 515958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); 516958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); 517958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); 518958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); 519958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); 520958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6); 521958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!scratch2().is(reg)); 522958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!scratch3().is(reg)); 523958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!scratch4().is(reg)); 524958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(receiver()); 525958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (heap()->InNewSpace(callback->data())) { 526958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Move(scratch3(), callback); 527958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(scratch3(), 528958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldMemOperand(scratch3(), ExecutableAccessorInfo::kDataOffset)); 529958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 530958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Move(scratch3(), Handle<Object>(callback->data(), isolate())); 531958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 532958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(scratch3()); 533958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(scratch3(), Heap::kUndefinedValueRootIndex); 534958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(scratch4(), scratch3()); 535958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(scratch3(), scratch4()); 536958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(scratch4(), Operand(ExternalReference::isolate_address(isolate()))); 537958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(scratch4(), reg); 538958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(name()); 539958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 540958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Abi for CallApiGetter 541958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register getter_address_reg = ApiGetterDescriptor::function_address(); 542958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 543958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Address getter_address = v8::ToCData<Address>(callback->getter()); 544958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ApiFunction fun(getter_address); 545958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; 546958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference ref = ExternalReference(&fun, type, isolate()); 547958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(getter_address_reg, Operand(ref)); 548958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 549958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CallApiGetterStub stub(isolate()); 550958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ TailCallStub(&stub); 551958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 552958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 553958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 554958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup( 555958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier LookupIterator* it, Register holder_reg) { 556958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(holder()->HasNamedInterceptor()); 557958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); 558958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 559958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compile the interceptor call, followed by inline code to load the 560958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // property from further up the prototype chain if the call fails. 561958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that the maps haven't changed. 562958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1())); 563958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 564958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Preserve the receiver register explicitly whenever it is different from the 565958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // holder and it is needed should the interceptor return without any result. 566958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // The ACCESSOR case needs the receiver to be passed into C++ code, the FIELD 567958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // case might cause a miss during the prototype check. 568958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool must_perform_prototype_check = 569958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier !holder().is_identical_to(it->GetHolder<JSObject>()); 570958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool must_preserve_receiver_reg = 571958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier !receiver().is(holder_reg) && 572958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier (it->state() == LookupIterator::ACCESSOR || must_perform_prototype_check); 573958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 574958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Save necessary data before invoking an interceptor. 575958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Requires a frame to make GC aware of pushed pointers. 576958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier { 577958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FrameAndConstantPoolScope frame_scope(masm(), StackFrame::INTERNAL); 578958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (must_preserve_receiver_reg) { 579958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(receiver(), holder_reg, this->name()); 580958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 581958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(holder_reg, this->name()); 582958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 583958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Invoke an interceptor. Note: map checks from receiver to 584958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // interceptor's holder has been compiled before (see a caller 585958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // of this method.) 586958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CompileCallLoadPropertyWithInterceptor( 587958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier masm(), receiver(), holder_reg, this->name(), holder(), 588958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier IC::kLoadPropertyWithInterceptorOnly); 589958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 590958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check if interceptor provided a value for property. If it's 591958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the case, return immediately. 592958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label interceptor_failed; 593958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex); 594958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(r3, scratch1()); 595958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&interceptor_failed); 596958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier frame_scope.GenerateLeaveFrame(); 597958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 598958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 599958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&interceptor_failed); 600958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ pop(this->name()); 601958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ pop(holder_reg); 602958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (must_preserve_receiver_reg) { 603958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ pop(receiver()); 604958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 605958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Leave the internal frame. 606958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 607958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 608958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateLoadPostInterceptor(it, holder_reg); 609958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 610958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 611958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 612958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) { 613958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Call the runtime system to load the interceptor. 614958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(holder()->HasNamedInterceptor()); 615958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); 616958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(), 617958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier holder()); 618958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 619958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference ref = ExternalReference( 620958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier IC_Utility(IC::kLoadPropertyWithInterceptor), isolate()); 621958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ TailCallExternalReference( 622958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); 623958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 624958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 625958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 626958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierHandle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( 627958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<JSObject> object, Handle<Name> name, 628958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<ExecutableAccessorInfo> callback) { 629958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register holder_reg = Frontend(receiver(), name); 630958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 631958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(receiver(), holder_reg); // receiver 632958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(ip, Operand(callback)); // callback info 633958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(ip); 634958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(ip, Operand(name)); 635958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(ip, value()); 636958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 637958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Do tail-call to the runtime system. 638958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference store_callback_property = 639958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); 640958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ TailCallExternalReference(store_callback_property, 5, 1); 641958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 642958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Return the generated code. 643958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return GetCode(kind(), Code::FAST, name); 644958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 645958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 646958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 647958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierHandle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( 648958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<Name> name) { 649958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(receiver(), this->name(), value()); 650958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 651958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Do tail-call to the runtime system. 652958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference store_ic_property = ExternalReference( 653958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); 654958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ TailCallExternalReference(store_ic_property, 3, 1); 655958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 656958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Return the generated code. 657958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return GetCode(kind(), Code::FAST, name); 658958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 659958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 660958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 661958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRegister NamedStoreHandlerCompiler::value() { 662958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return StoreDescriptor::ValueRegister(); 663958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 664958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 665958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 666958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierHandle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( 667958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { 668958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label miss; 669958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FrontendHeader(receiver(), name, &miss); 670958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 671958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Get the value from the cell. 672958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register result = StoreDescriptor::ValueRegister(); 673958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(result, Operand(cell)); 674958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(result, FieldMemOperand(result, Cell::kValueOffset)); 675958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 676958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check for deleted property if property can actually be deleted. 677958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (is_configurable) { 678958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 679958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(result, ip); 680958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&miss); 681958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 682958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 683958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Counters* counters = isolate()->counters(); 684958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ IncrementCounter(counters->named_load_global_stub(), 1, r4, r6); 685958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 686958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 687958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FrontendFooter(name, &miss); 688958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 689958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Return the generated code. 690958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return GetCode(kind(), Code::NORMAL, name); 691958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 692958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 693958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 694958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#undef __ 695958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 696958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} // namespace v8::internal 697958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 698958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif // V8_TARGET_ARCH_ARM 699