handler-compiler-ppc.cc revision f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3
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#if V8_TARGET_ARCH_PPC 6958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 7f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch#include "src/ic/handler-compiler.h" 8109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 93b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#include "src/api-arguments.h" 10109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#include "src/field-type.h" 11109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#include "src/ic/call-optimization.h" 12958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/ic/ic.h" 13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/isolate-inl.h" 14958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 15958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace v8 { 16958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace internal { 17958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 18958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#define __ ACCESS_MASM(masm) 19958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 20958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 21958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::GenerateLoadViaGetter( 22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder, 23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int accessor_index, int expected_arguments, Register scratch) { 24958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // ----------- S t a t e ------------- 25958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- r3 : receiver 26958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- r5 : name 27958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- lr : return address 28958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // ----------------------------------- 29958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier { 30958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 31958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Save context register 333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ push(cp); 343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (accessor_index >= 0) { 36014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!holder.is(scratch)); 37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!receiver.is(scratch)); 38958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Call the JavaScript getter with the receiver on the stack. 39014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (map->IsJSGlobalObjectMap()) { 40958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Swap in the global receiver. 41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(scratch, 42958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); 43014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch receiver = scratch; 44958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 45958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(receiver); 46014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadAccessor(r4, holder, accessor_index, ACCESSOR_GETTER); 473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ li(r3, Operand::Zero()); 483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Call(masm->isolate()->builtins()->CallFunction( 493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch ConvertReceiverMode::kNotNullOrUndefined), 503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch RelocInfo::CODE_TARGET); 51958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 52958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If we generate a global code snippet for deoptimization only, remember 53958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the place to continue after deoptimization. 54958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); 55958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 56958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 57958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Restore context register. 583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ pop(cp); 59958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 60958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 61958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 62958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 63958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 64958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::GenerateStoreViaSetter( 65014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder, 66014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int accessor_index, int expected_arguments, Register scratch) { 67958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // ----------- S t a t e ------------- 68958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // -- lr : return address 69958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // ----------------------------------- 70958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier { 71958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 72958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Save context register 74958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Save value register, so we can restore it later. 753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Push(cp, value()); 76958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 77014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (accessor_index >= 0) { 78014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!holder.is(scratch)); 79014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!receiver.is(scratch)); 80014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!value().is(scratch)); 81958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Call the JavaScript setter with receiver and value on the stack. 82014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (map->IsJSGlobalObjectMap()) { 83958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Swap in the global receiver. 84014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(scratch, 85958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); 86014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch receiver = scratch; 87958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 88958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(receiver, value()); 89014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadAccessor(r4, holder, accessor_index, ACCESSOR_SETTER); 903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ li(r3, Operand(1)); 913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Call(masm->isolate()->builtins()->CallFunction( 923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch ConvertReceiverMode::kNotNullOrUndefined), 933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch RelocInfo::CODE_TARGET); 94958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 95958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If we generate a global code snippet for deoptimization only, remember 96958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the place to continue after deoptimization. 97958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset()); 98958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 99958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 100958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // We have to return the passed value, not the return value of the setter. 101958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Restore context register. 1023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Pop(cp, r3); 103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 104958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid PropertyHandlerCompiler::PushVectorAndSlot(Register vector, 109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register slot) { 110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MacroAssembler* masm = this->masm(); 111f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(LoadWithVectorDescriptor::kSlot < 112f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch LoadWithVectorDescriptor::kVector); 113f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(StoreWithVectorDescriptor::kSlot < 114f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreWithVectorDescriptor::kVector); 115f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(StoreTransitionDescriptor::kSlot < 116f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreTransitionDescriptor::kVector); 117f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Push(slot, vector); 118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid PropertyHandlerCompiler::PopVectorAndSlot(Register vector, Register slot) { 122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MacroAssembler* masm = this->masm(); 123f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Pop(slot, vector); 124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid PropertyHandlerCompiler::DiscardVectorAndSlot() { 128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MacroAssembler* masm = this->masm(); 129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Remove vector and slot. 130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ addi(sp, sp, Operand(2 * kPointerSize)); 131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 133f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid PropertyHandlerCompiler::PushReturnAddress(Register tmp) { 134f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // No-op. Return address is in lr register. 135f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 136f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 137f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid PropertyHandlerCompiler::PopReturnAddress(Register tmp) { 138f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // No-op. Return address is in lr register. 139f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( 142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, Label* miss_label, Register receiver, 143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<Name> name, Register scratch0, Register scratch1) { 144958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(name->IsUniqueName()); 145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!receiver.is(scratch0)); 146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Counters* counters = masm->isolate()->counters(); 147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); 148958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); 149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 150958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label done; 151958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const int kInterceptorOrAccessCheckNeededMask = 153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); 154958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Bail out if the receiver has a named interceptor or requires access checks. 156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register map = scratch1; 157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); 158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); 159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, scratch0, Operand(kInterceptorOrAccessCheckNeededMask)); 160958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(miss_label, cr0); 161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that receiver is a JSObject. 163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); 164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpi(scratch0, Operand(FIRST_JS_RECEIVER_TYPE)); 165958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ blt(miss_label); 166958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 167958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load properties array. 168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register properties = scratch0; 169958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 170958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that the properties array is a dictionary. 171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(map, FieldMemOperand(properties, HeapObject::kMapOffset)); 172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register tmp = properties; 173958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); 174958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(map, tmp); 175958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(miss_label); 176958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 177958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Restore the temporarily used register. 178958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 179958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 180958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 181958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NameDictionaryLookupStub::GenerateNegativeLookup( 182958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier masm, miss_label, &done, receiver, properties, name, scratch1); 183958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&done); 184958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); 185958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 186958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 187958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 188958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype( 189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MacroAssembler* masm, int index, Register result, Label* miss) { 190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadNativeContextSlot(index, result); 191958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load its initial map. The global functions all have initial maps. 192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(result, 193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FieldMemOperand(result, JSFunction::kPrototypeOrInitialMapOffset)); 194958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load the prototype from the initial map. 195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(result, FieldMemOperand(result, Map::kPrototypeOffset)); 196958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 197958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 198958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 199958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype( 200958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, Register receiver, Register scratch1, 201958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch2, Label* miss_label) { 202958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); 203958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r3, scratch1); 204958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 205958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 206958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 207958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 208958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Generate code to check that a global property cell is empty. Create 209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// the property cell at compilation time if no cell exists for the 210958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// property. 211958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid PropertyHandlerCompiler::GenerateCheckPropertyCell( 212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, 213958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch, Label* miss) { 214f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<PropertyCell> cell = JSGlobalObject::EnsureEmptyPropertyCell( 215f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch global, name, PropertyCellType::kInvalidated); 21613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Isolate* isolate = masm->isolate(); 21713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(cell->value()->IsTheHole(isolate)); 21813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell); 219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadWeakValue(scratch, weak_cell, miss); 220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(scratch, FieldMemOperand(scratch, PropertyCell::kValueOffset)); 221958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 222958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(scratch, ip); 223958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(miss); 224958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 225958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void PushInterceptorArguments(MacroAssembler* masm, Register receiver, 228958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register holder, Register name, 229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<JSObject> holder_obj) { 230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); 231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 1); 232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 2); 233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 3); 234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(name); 235958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(receiver); 236958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(holder); 237958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 238958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 239958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 240958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void CompileCallLoadPropertyWithInterceptor( 241958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, Register receiver, Register holder, Register name, 242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<JSObject> holder_obj, Runtime::FunctionId id) { 243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(NamedLoadHandlerCompiler::kInterceptorArgsLength == 244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Runtime::FunctionForId(id)->nargs); 245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PushInterceptorArguments(masm, receiver, holder, name, holder_obj); 246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(id); 247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 248958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 249958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 250958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Generate call to api function. 251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid PropertyHandlerCompiler::GenerateApiAccessorCall( 252958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, const CallOptimization& optimization, 253958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<Map> receiver_map, Register receiver, Register scratch_in, 254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool is_store, Register store_parameter, Register accessor_holder, 255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int accessor_index) { 256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!accessor_holder.is(scratch_in)); 257958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!receiver.is(scratch_in)); 258958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(receiver); 259958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Write the arguments to stack frame. 260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (is_store) { 261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!receiver.is(store_parameter)); 262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!scratch_in.is(store_parameter)); 263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(store_parameter); 264958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 265958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(optimization.is_simple_api_call()); 266958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Abi for CallApiCallbackStub. 268958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register callee = r3; 269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register data = r7; 270958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register holder = r5; 271958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register api_function_address = r4; 272958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Put callee in place. 274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadAccessor(callee, accessor_holder, accessor_index, 275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch is_store ? ACCESSOR_SETTER : ACCESSOR_GETTER); 276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 277958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Put holder in place. 278958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CallOptimization::HolderLookup holder_lookup; 279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int holder_depth = 0; 280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch optimization.LookupHolderOfExpectedType(receiver_map, &holder_lookup, 281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch &holder_depth); 282958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier switch (holder_lookup) { 283958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case CallOptimization::kHolderIsReceiver: 284958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Move(holder, receiver); 285958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 286958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case CallOptimization::kHolderFound: 287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(holder, FieldMemOperand(receiver, HeapObject::kMapOffset)); 288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(holder, FieldMemOperand(holder, Map::kPrototypeOffset)); 289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 1; i < holder_depth; i++) { 290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(holder, FieldMemOperand(holder, HeapObject::kMapOffset)); 291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(holder, FieldMemOperand(holder, Map::kPrototypeOffset)); 292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 293958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 294958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case CallOptimization::kHolderNotFound: 295958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier UNREACHABLE(); 296958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 297958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 299958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Isolate* isolate = masm->isolate(); 300958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 301958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool call_data_undefined = false; 302014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Put call data in place. 30313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (api_call_info->data()->IsUndefined(isolate)) { 304958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier call_data_undefined = true; 305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(data, Heap::kUndefinedValueRootIndex); 306958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 307109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (optimization.is_constant_call()) { 308109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(data, 309109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FieldMemOperand(callee, JSFunction::kSharedFunctionInfoOffset)); 310109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(data, 311109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FieldMemOperand(data, SharedFunctionInfo::kFunctionDataOffset)); 312109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(data, 313109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FieldMemOperand(data, FunctionTemplateInfo::kCallCodeOffset)); 314109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else { 315109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(data, 316109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FieldMemOperand(callee, FunctionTemplateInfo::kCallCodeOffset)); 317109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 318014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(data, FieldMemOperand(data, CallHandlerInfo::kDataOffset)); 319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (api_call_info->fast_handler()->IsCode()) { 322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Just tail call into the fast handler if present. 323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(handle(Code::cast(api_call_info->fast_handler())), 324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo::CODE_TARGET); 325014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return; 326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Put api_function_address in place. 329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Address function_address = v8::ToCData<Address>(api_call_info->callback()); 330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ApiFunction fun(function_address); 331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference::Type type = ExternalReference::DIRECT_API_CALL; 332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference ref = ExternalReference(&fun, type, masm->isolate()); 333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(api_function_address, Operand(ref)); 334958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Jump to stub. 3363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch CallApiCallbackStub stub(isolate, is_store, call_data_undefined, 337109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch !optimization.is_constant_call()); 338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ TailCallStub(&stub); 339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 341958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#undef __ 342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#define __ ACCESS_MASM(masm()) 343958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 344958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 345958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, 346958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<Name> name) { 347958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!label->is_unused()) { 348958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(label); 349958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(this->name(), Operand(name)); 350958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 351958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 352958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 353958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 354014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) { 355958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(this->name(), Operand(name)); 356958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 357958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 358958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition, 360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register map_reg, 361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register scratch, 362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label* miss) { 363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<WeakCell> cell = Map::WeakCellForMap(transition); 364014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!map_reg.is(scratch)); 365014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadWeakValue(map_reg, cell, miss); 366014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (transition->CanBeDeprecated()) { 367014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lwz(scratch, FieldMemOperand(map_reg, Map::kBitField3Offset)); 368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ DecodeField<Map::Deprecated>(r0, scratch, SetRC); 369014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(miss, cr0); 370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid NamedStoreHandlerCompiler::GenerateConstantCheck(Register map_reg, 375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int descriptor, 376958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register value_reg, 377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register scratch, 378958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label* miss_label) { 379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!map_reg.is(scratch)); 380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!map_reg.is(value_reg)); 381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!value_reg.is(scratch)); 382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadInstanceDescriptors(map_reg, scratch); 383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(scratch, FieldMemOperand( 384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch scratch, DescriptorArray::GetValueOffset(descriptor))); 385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(value_reg, scratch); 386958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(miss_label); 387958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 388958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 389109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid NamedStoreHandlerCompiler::GenerateFieldTypeChecks(FieldType* field_type, 390958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register value_reg, 391958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label* miss_label) { 392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register map_reg = scratch1(); 393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register scratch = scratch2(); 394014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!value_reg.is(map_reg)); 395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!value_reg.is(scratch)); 396958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfSmi(value_reg, miss_label); 397109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (field_type->IsClass()) { 398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(map_reg, FieldMemOperand(value_reg, HeapObject::kMapOffset)); 399109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CmpWeakValue(map_reg, Map::WeakCellForMap(field_type->AsClass()), 400109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch scratch); 401109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(miss_label); 402958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 403958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 404958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 405958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 406958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRegister PropertyHandlerCompiler::CheckPrototypes( 407958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register object_reg, Register holder_reg, Register scratch1, 408014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register scratch2, Handle<Name> name, Label* miss, PrototypeCheckType check, 409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ReturnHolder return_what) { 410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Map> receiver_map = map(); 411958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 412958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Make sure there's no overlap between holder and object registers. 413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && 415958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier !scratch2.is(scratch1)); 416958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 41713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Handle<Cell> validity_cell = 41813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); 41913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (!validity_cell.is_null()) { 42013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value()); 42113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ mov(scratch1, Operand(validity_cell)); 42213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ LoadP(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset)); 42313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ CmpSmiLiteral(scratch1, Smi::FromInt(Map::kPrototypeChainValid), r0); 42413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ bne(miss); 42513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 42713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // The prototype chain of primitives (and their JSValue wrappers) depends 42813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // on the native context, which can't be guarded by validity cells. 42913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // |object_reg| holds the native context specific prototype in this case; 43013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // we need to check its map. 43113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (check == CHECK_ALL_MAPS) { 43213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ LoadP(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset)); 43313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); 43413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ CmpWeakValue(scratch1, cell, scratch2); 43513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ b(ne, miss); 436014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 437014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 438958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Keep track of the current object in register reg. 439958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register reg = object_reg; 440958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int depth = 0; 441958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 442958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<JSObject> current = Handle<JSObject>::null(); 443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (receiver_map->IsJSGlobalObjectMap()) { 444014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch current = isolate()->global_object(); 445014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 446014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check access rights to the global object. This has to happen after 447014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // the map check so that we know that the object is actually a global 448014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // object. 449014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // This allows us to install generated handlers for accesses to the 450014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // global proxy (as opposed to using slow ICs). See corresponding code 451014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // in LookupForRead(). 452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (receiver_map->IsJSGlobalProxyMap()) { 453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CheckAccessGlobalProxy(reg, scratch2, miss); 454958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 455014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 456958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<JSObject> prototype = Handle<JSObject>::null(); 457958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<Map> current_map = receiver_map; 458958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<Map> holder_map(holder()->map()); 459958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Traverse the prototype chain and check the maps in the prototype chain for 460958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // fast and global objects or do negative lookup for normal objects. 461958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier while (!current_map.is_identical_to(holder_map)) { 462958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ++depth; 463958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 464958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Only global objects and objects that do not require access 465958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // checks are allowed in stubs. 466958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(current_map->IsJSGlobalProxyMap() || 467958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier !current_map->is_access_check_needed()); 468958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 469958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier prototype = handle(JSObject::cast(current_map->prototype())); 47013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (current_map->IsJSGlobalObjectMap()) { 47113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), 47213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch name, scratch2, miss); 47313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } else if (current_map->is_dictionary_map()) { 474958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. 475958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!name->IsUniqueName()) { 476958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(name->IsString()); 477958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier name = factory()->InternalizeString(Handle<String>::cast(name)); 478958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 479958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(current.is_null() || 480958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier current->property_dictionary()->FindEntry(name) == 481958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NameDictionary::kNotFound); 482958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 48313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (depth > 1) { 484014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // TODO(jkummerow): Cache and re-use weak cell. 485014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss); 486014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 487958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, 488958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier scratch2); 489958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 490958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 491014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch reg = holder_reg; // From now on the object will be in holder_reg. 492958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Go to the next object in the prototype chain. 493958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier current = prototype; 494958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier current_map = handle(current->map()); 495958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 496958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!current_map->IsJSGlobalProxyMap()); 498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 499958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Log the check depth. 500958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); 501958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 502014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool return_holder = return_what == RETURN_HOLDER; 50313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (return_holder && depth != 0) { 504014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss); 505958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 506958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 507958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Return the register containing the holder. 508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return return_holder ? reg : no_reg; 509958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 510958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 511958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 512958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { 513958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!miss->is_unused()) { 514958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label success; 515958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&success); 516958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(miss); 517014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IC::ICUseVector(kind())) { 518014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(kind() == Code::LOAD_IC); 519014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PopVectorAndSlot(); 520014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 521958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier TailCallBuiltin(masm(), MissBuiltin(kind())); 522958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&success); 523958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 524958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 525958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 526958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 527958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { 528958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!miss->is_unused()) { 529958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label success; 530958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&success); 531958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateRestoreName(miss, name); 532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IC::ICUseVector(kind())) PopVectorAndSlot(); 533958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier TailCallBuiltin(masm(), MissBuiltin(kind())); 534958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&success); 535958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 536958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 537958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 538958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 539958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { 540958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Return the constant value. 541958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Move(r3, value); 542958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 543958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 544958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 545958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 546958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup( 547958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier LookupIterator* it, Register holder_reg) { 548958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(holder()->HasNamedInterceptor()); 54913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate())); 550958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 551958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compile the interceptor call, followed by inline code to load the 552958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // property from further up the prototype chain if the call fails. 553958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that the maps haven't changed. 554958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1())); 555958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 556958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Preserve the receiver register explicitly whenever it is different from the 557958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // holder and it is needed should the interceptor return without any result. 558958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // The ACCESSOR case needs the receiver to be passed into C++ code, the FIELD 559958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // case might cause a miss during the prototype check. 560958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool must_perform_prototype_check = 561958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier !holder().is_identical_to(it->GetHolder<JSObject>()); 562958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool must_preserve_receiver_reg = 563958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier !receiver().is(holder_reg) && 564958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier (it->state() == LookupIterator::ACCESSOR || must_perform_prototype_check); 565958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 566958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Save necessary data before invoking an interceptor. 567958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Requires a frame to make GC aware of pushed pointers. 568958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier { 569958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FrameAndConstantPoolScope frame_scope(masm(), StackFrame::INTERNAL); 570958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (must_preserve_receiver_reg) { 571958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(receiver(), holder_reg, this->name()); 572958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 573958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(holder_reg, this->name()); 574958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 575014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch InterceptorVectorSlotPush(holder_reg); 576958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Invoke an interceptor. Note: map checks from receiver to 577958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // interceptor's holder has been compiled before (see a caller 578958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // of this method.) 579958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CompileCallLoadPropertyWithInterceptor( 580958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier masm(), receiver(), holder_reg, this->name(), holder(), 581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Runtime::kLoadPropertyWithInterceptorOnly); 582958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 583958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check if interceptor provided a value for property. If it's 584958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the case, return immediately. 585958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label interceptor_failed; 586958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex); 587958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(r3, scratch1()); 588958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&interceptor_failed); 589958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier frame_scope.GenerateLeaveFrame(); 590958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 591958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 592958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&interceptor_failed); 593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch InterceptorVectorSlotPop(holder_reg); 594958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ pop(this->name()); 595958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ pop(holder_reg); 596958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (must_preserve_receiver_reg) { 597958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ pop(receiver()); 598958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 599958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Leave the internal frame. 600958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 601958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 602958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateLoadPostInterceptor(it, holder_reg); 603958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 604958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 605958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 606958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) { 607958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Call the runtime system to load the interceptor. 608958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(holder()->HasNamedInterceptor()); 60913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate())); 610958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(), 611958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier holder()); 612958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 613014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kLoadPropertyWithInterceptor); 614958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 615958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 616f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid NamedStoreHandlerCompiler::ZapStackArgumentsRegisterAliases() { 617f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(!StoreWithVectorDescriptor::kPassLastArgsOnStack); 618f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 619958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 620958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierHandle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( 621109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> callback, 622109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch LanguageMode language_mode) { 623014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register holder_reg = Frontend(name); 624958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 625958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(receiver(), holder_reg); // receiver 626014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 627014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the callback cannot leak, then push the callback directly, 628014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // otherwise wrap it in a weak cell. 62913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (callback->data()->IsUndefined(isolate()) || callback->data()->IsSmi()) { 630014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ip, Operand(callback)); 631014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 632014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<WeakCell> cell = isolate()->factory()->NewWeakCell(callback); 633014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ip, Operand(cell)); 634014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 635958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(ip); 636958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(ip, Operand(name)); 637958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(ip, value()); 638109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(Smi::FromInt(language_mode)); 639958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 640958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Do tail-call to the runtime system. 641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kStoreCallbackProperty); 642958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 643958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Return the generated code. 644bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return GetCode(kind(), name); 645958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 646958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 647958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 648958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRegister NamedStoreHandlerCompiler::value() { 649958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return StoreDescriptor::ValueRegister(); 650958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 651958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 652958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 653958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierHandle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( 654958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { 655958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label miss; 656014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IC::ICUseVector(kind())) { 657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PushVectorAndSlot(); 658014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 659014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrontendHeader(receiver(), name, &miss, DONT_RETURN_ANYTHING); 660958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 661958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Get the value from the cell. 662958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register result = StoreDescriptor::ValueRegister(); 663014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell); 664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadWeakValue(result, weak_cell, &miss); 665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(result, FieldMemOperand(result, PropertyCell::kValueOffset)); 666958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 667958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check for deleted property if property can actually be deleted. 668958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (is_configurable) { 669958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 670958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(result, ip); 671958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&miss); 672958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 673958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 674958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Counters* counters = isolate()->counters(); 675109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ IncrementCounter(counters->ic_named_load_global_stub(), 1, r4, r6); 676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IC::ICUseVector(kind())) { 677014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DiscardVectorAndSlot(); 678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 679958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 680958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 681958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FrontendFooter(name, &miss); 682958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 683958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Return the generated code. 684bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return GetCode(kind(), name); 685958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 686958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 687958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 688958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#undef __ 689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 691958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 692958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif // V8_TARGET_ARCH_ARM 693