handler-compiler-ppc.cc revision 13e2dadd00298019ed862f2b2fc5068bba730bcf
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(); 111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(vector, slot); 112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid PropertyHandlerCompiler::PopVectorAndSlot(Register vector, Register slot) { 116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MacroAssembler* masm = this->masm(); 117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(vector, slot); 118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid PropertyHandlerCompiler::DiscardVectorAndSlot() { 122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MacroAssembler* masm = this->masm(); 123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Remove vector and slot. 124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ addi(sp, sp, Operand(2 * kPointerSize)); 125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( 129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, Label* miss_label, Register receiver, 130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<Name> name, Register scratch0, Register scratch1) { 131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(name->IsUniqueName()); 132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!receiver.is(scratch0)); 133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Counters* counters = masm->isolate()->counters(); 134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); 135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); 136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label done; 138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 139958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const int kInterceptorOrAccessCheckNeededMask = 140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); 141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Bail out if the receiver has a named interceptor or requires access checks. 143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register map = scratch1; 144958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); 145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); 146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ andi(r0, scratch0, Operand(kInterceptorOrAccessCheckNeededMask)); 147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(miss_label, cr0); 148958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that receiver is a JSObject. 150958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ lbz(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); 151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpi(scratch0, Operand(FIRST_JS_RECEIVER_TYPE)); 152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ blt(miss_label); 153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 154958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load properties array. 155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register properties = scratch0; 156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that the properties array is a dictionary. 158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(map, FieldMemOperand(properties, HeapObject::kMapOffset)); 159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register tmp = properties; 160958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); 161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(map, tmp); 162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(miss_label); 163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Restore the temporarily used register. 165958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadP(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 166958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 167958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NameDictionaryLookupStub::GenerateNegativeLookup( 169958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier masm, miss_label, &done, receiver, properties, name, scratch1); 170958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&done); 171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); 172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 173958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 174958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 175958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype( 176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MacroAssembler* masm, int index, Register result, Label* miss) { 177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadNativeContextSlot(index, result); 178958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load its initial map. The global functions all have initial maps. 179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(result, 180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FieldMemOperand(result, JSFunction::kPrototypeOrInitialMapOffset)); 181958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load the prototype from the initial map. 182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(result, FieldMemOperand(result, Map::kPrototypeOffset)); 183958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 184958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 185958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 186958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype( 187958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, Register receiver, Register scratch1, 188958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch2, Label* miss_label) { 189958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); 190958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mr(r3, scratch1); 191958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 192958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 193958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 194958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 195958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Generate code to check that a global property cell is empty. Create 196958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// the property cell at compilation time if no cell exists for the 197958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// property. 198958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid PropertyHandlerCompiler::GenerateCheckPropertyCell( 199958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, 200958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch, Label* miss) { 201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<PropertyCell> cell = JSGlobalObject::EnsurePropertyCell(global, name); 20213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Isolate* isolate = masm->isolate(); 20313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(cell->value()->IsTheHole(isolate)); 20413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell); 205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadWeakValue(scratch, weak_cell, miss); 206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(scratch, FieldMemOperand(scratch, PropertyCell::kValueOffset)); 207958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 208958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(scratch, ip); 209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(miss); 210958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 211958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 213958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void PushInterceptorArguments(MacroAssembler* masm, Register receiver, 214958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register holder, Register name, 215958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<JSObject> holder_obj) { 216958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); 217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 1); 218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 2); 219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 3); 220958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(name); 221958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(receiver); 222958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(holder); 223958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 224958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 225958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void CompileCallLoadPropertyWithInterceptor( 227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, Register receiver, Register holder, Register name, 228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<JSObject> holder_obj, Runtime::FunctionId id) { 229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(NamedLoadHandlerCompiler::kInterceptorArgsLength == 230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Runtime::FunctionForId(id)->nargs); 231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PushInterceptorArguments(masm, receiver, holder, name, holder_obj); 232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(id); 233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 235958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 236958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Generate call to api function. 237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid PropertyHandlerCompiler::GenerateApiAccessorCall( 238958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, const CallOptimization& optimization, 239958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<Map> receiver_map, Register receiver, Register scratch_in, 240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool is_store, Register store_parameter, Register accessor_holder, 241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int accessor_index) { 242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!accessor_holder.is(scratch_in)); 243958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!receiver.is(scratch_in)); 244958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(receiver); 245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Write the arguments to stack frame. 246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (is_store) { 247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!receiver.is(store_parameter)); 248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!scratch_in.is(store_parameter)); 249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(store_parameter); 250958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 251958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(optimization.is_simple_api_call()); 252958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Abi for CallApiCallbackStub. 254958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register callee = r3; 255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register data = r7; 256958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register holder = r5; 257958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register api_function_address = r4; 258958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Put callee in place. 260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadAccessor(callee, accessor_holder, accessor_index, 261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch is_store ? ACCESSOR_SETTER : ACCESSOR_GETTER); 262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 263958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Put holder in place. 264958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CallOptimization::HolderLookup holder_lookup; 265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int holder_depth = 0; 266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch optimization.LookupHolderOfExpectedType(receiver_map, &holder_lookup, 267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch &holder_depth); 268958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier switch (holder_lookup) { 269958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case CallOptimization::kHolderIsReceiver: 270958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Move(holder, receiver); 271958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 272958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case CallOptimization::kHolderFound: 273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(holder, FieldMemOperand(receiver, HeapObject::kMapOffset)); 274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(holder, FieldMemOperand(holder, Map::kPrototypeOffset)); 275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 1; i < holder_depth; i++) { 276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(holder, FieldMemOperand(holder, HeapObject::kMapOffset)); 277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(holder, FieldMemOperand(holder, Map::kPrototypeOffset)); 278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 279958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 280958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case CallOptimization::kHolderNotFound: 281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier UNREACHABLE(); 282958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 283958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 284958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 285958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Isolate* isolate = masm->isolate(); 286958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool call_data_undefined = false; 288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Put call data in place. 28913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (api_call_info->data()->IsUndefined(isolate)) { 290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier call_data_undefined = true; 291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(data, Heap::kUndefinedValueRootIndex); 292958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 293109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (optimization.is_constant_call()) { 294109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(data, 295109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FieldMemOperand(callee, JSFunction::kSharedFunctionInfoOffset)); 296109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(data, 297109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FieldMemOperand(data, SharedFunctionInfo::kFunctionDataOffset)); 298109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(data, 299109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FieldMemOperand(data, FunctionTemplateInfo::kCallCodeOffset)); 300109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else { 301109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadP(data, 302109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FieldMemOperand(callee, FunctionTemplateInfo::kCallCodeOffset)); 303109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 304014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(data, FieldMemOperand(data, CallHandlerInfo::kDataOffset)); 305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (api_call_info->fast_handler()->IsCode()) { 308014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Just tail call into the fast handler if present. 309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(handle(Code::cast(api_call_info->fast_handler())), 310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo::CODE_TARGET); 311014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return; 312958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 313958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 314958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Put api_function_address in place. 315958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Address function_address = v8::ToCData<Address>(api_call_info->callback()); 316958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ApiFunction fun(function_address); 317958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference::Type type = ExternalReference::DIRECT_API_CALL; 318958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExternalReference ref = ExternalReference(&fun, type, masm->isolate()); 319958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(api_function_address, Operand(ref)); 320958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 321958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Jump to stub. 3223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch CallApiCallbackStub stub(isolate, is_store, call_data_undefined, 323109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch !optimization.is_constant_call()); 324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ TailCallStub(&stub); 325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 328014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic void StoreIC_PushArgs(MacroAssembler* masm) { 329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(), 330014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch StoreDescriptor::ValueRegister(), 331014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VectorStoreICDescriptor::SlotRegister(), 332014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VectorStoreICDescriptor::VectorRegister()); 333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 334014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 335014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 336014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid NamedStoreHandlerCompiler::GenerateSlow(MacroAssembler* masm) { 337014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch StoreIC_PushArgs(masm); 338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // The slow case calls into the runtime to complete the store without causing 340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // an IC miss that would otherwise cause a transition to the generic stub. 341014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kStoreIC_Slow); 342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 343958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 344958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 345958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) { 346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch StoreIC_PushArgs(masm); 347958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 348958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // The slow case calls into the runtime to complete the store without causing 349958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // an IC miss that would otherwise cause a transition to the generic stub. 350014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow); 351958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 352958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 353958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 354958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#undef __ 355958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#define __ ACCESS_MASM(masm()) 356958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 357958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 358958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, 359958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<Name> name) { 360958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!label->is_unused()) { 361958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(label); 362958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(this->name(), Operand(name)); 363958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 364958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 365958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 366958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 367014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) { 368958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(this->name(), Operand(name)); 369958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 370958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 371958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid NamedStoreHandlerCompiler::RearrangeVectorAndSlot( 373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register current_map, Register destination_map) { 374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(false); // Not implemented. 375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition, 379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register map_reg, 380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register scratch, 381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label* miss) { 382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<WeakCell> cell = Map::WeakCellForMap(transition); 383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!map_reg.is(scratch)); 384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadWeakValue(map_reg, cell, miss); 385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (transition->CanBeDeprecated()) { 386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lwz(scratch, FieldMemOperand(map_reg, Map::kBitField3Offset)); 387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ DecodeField<Map::Deprecated>(r0, scratch, SetRC); 388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bne(miss, cr0); 389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid NamedStoreHandlerCompiler::GenerateConstantCheck(Register map_reg, 394014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int descriptor, 395958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register value_reg, 396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register scratch, 397958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label* miss_label) { 398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!map_reg.is(scratch)); 399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!map_reg.is(value_reg)); 400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!value_reg.is(scratch)); 401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadInstanceDescriptors(map_reg, scratch); 402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(scratch, FieldMemOperand( 403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch scratch, DescriptorArray::GetValueOffset(descriptor))); 404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(value_reg, scratch); 405958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bne(miss_label); 406958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 407958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 408109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid NamedStoreHandlerCompiler::GenerateFieldTypeChecks(FieldType* field_type, 409958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register value_reg, 410958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label* miss_label) { 411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register map_reg = scratch1(); 412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register scratch = scratch2(); 413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!value_reg.is(map_reg)); 414014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!value_reg.is(scratch)); 415958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfSmi(value_reg, miss_label); 416109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (field_type->IsClass()) { 417014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(map_reg, FieldMemOperand(value_reg, HeapObject::kMapOffset)); 418109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CmpWeakValue(map_reg, Map::WeakCellForMap(field_type->AsClass()), 419109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch scratch); 420109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bne(miss_label); 421958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 422958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 423958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 424958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 425958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRegister PropertyHandlerCompiler::CheckPrototypes( 426958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register object_reg, Register holder_reg, Register scratch1, 427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register scratch2, Handle<Name> name, Label* miss, PrototypeCheckType check, 428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ReturnHolder return_what) { 429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Map> receiver_map = map(); 430958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 431958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Make sure there's no overlap between holder and object registers. 432958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 433958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && 434958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier !scratch2.is(scratch1)); 435958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 43613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Handle<Cell> validity_cell = 43713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); 43813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (!validity_cell.is_null()) { 43913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value()); 44013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ mov(scratch1, Operand(validity_cell)); 44113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ LoadP(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset)); 44213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ CmpSmiLiteral(scratch1, Smi::FromInt(Map::kPrototypeChainValid), r0); 44313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ bne(miss); 44413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 445014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 44613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // The prototype chain of primitives (and their JSValue wrappers) depends 44713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // on the native context, which can't be guarded by validity cells. 44813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // |object_reg| holds the native context specific prototype in this case; 44913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // we need to check its map. 45013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (check == CHECK_ALL_MAPS) { 45113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ LoadP(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset)); 45213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); 45313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ CmpWeakValue(scratch1, cell, scratch2); 45413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ b(ne, miss); 455014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 456014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 457958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Keep track of the current object in register reg. 458958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register reg = object_reg; 459958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int depth = 0; 460958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 461958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<JSObject> current = Handle<JSObject>::null(); 462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (receiver_map->IsJSGlobalObjectMap()) { 463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch current = isolate()->global_object(); 464014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 465014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check access rights to the global object. This has to happen after 466014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // the map check so that we know that the object is actually a global 467014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // object. 468014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // This allows us to install generated handlers for accesses to the 469014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // global proxy (as opposed to using slow ICs). See corresponding code 470014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // in LookupForRead(). 471014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (receiver_map->IsJSGlobalProxyMap()) { 472014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CheckAccessGlobalProxy(reg, scratch2, miss); 473958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 474014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 475958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<JSObject> prototype = Handle<JSObject>::null(); 476958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<Map> current_map = receiver_map; 477958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<Map> holder_map(holder()->map()); 478958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Traverse the prototype chain and check the maps in the prototype chain for 479958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // fast and global objects or do negative lookup for normal objects. 480958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier while (!current_map.is_identical_to(holder_map)) { 481958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ++depth; 482958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 483958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Only global objects and objects that do not require access 484958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // checks are allowed in stubs. 485958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(current_map->IsJSGlobalProxyMap() || 486958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier !current_map->is_access_check_needed()); 487958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 488958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier prototype = handle(JSObject::cast(current_map->prototype())); 48913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (current_map->IsJSGlobalObjectMap()) { 49013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), 49113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch name, scratch2, miss); 49213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } else if (current_map->is_dictionary_map()) { 493958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. 494958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!name->IsUniqueName()) { 495958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(name->IsString()); 496958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier name = factory()->InternalizeString(Handle<String>::cast(name)); 497958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 498958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(current.is_null() || 499958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier current->property_dictionary()->FindEntry(name) == 500958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NameDictionary::kNotFound); 501958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 50213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (depth > 1) { 503014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // TODO(jkummerow): Cache and re-use weak cell. 504014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss); 505014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 506958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, 507958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier scratch2); 508958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 509958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch reg = holder_reg; // From now on the object will be in holder_reg. 511958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Go to the next object in the prototype chain. 512958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier current = prototype; 513958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier current_map = handle(current->map()); 514958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 515958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!current_map->IsJSGlobalProxyMap()); 517014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 518958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Log the check depth. 519958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); 520958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 521014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool return_holder = return_what == RETURN_HOLDER; 52213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (return_holder && depth != 0) { 523014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss); 524958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 525958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 526958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Return the register containing the holder. 527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return return_holder ? reg : no_reg; 528958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 529958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 530958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 531958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { 532958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!miss->is_unused()) { 533958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label success; 534958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&success); 535958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(miss); 536014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IC::ICUseVector(kind())) { 537014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(kind() == Code::LOAD_IC); 538014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PopVectorAndSlot(); 539014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 540958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier TailCallBuiltin(masm(), MissBuiltin(kind())); 541958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&success); 542958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 543958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 544958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 545958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 546958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { 547958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!miss->is_unused()) { 548958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label success; 549958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&success); 550958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateRestoreName(miss, name); 551014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IC::ICUseVector(kind())) PopVectorAndSlot(); 552958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier TailCallBuiltin(masm(), MissBuiltin(kind())); 553958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&success); 554958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 555958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 556958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 557958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 558958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { 559958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Return the constant value. 560958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Move(r3, value); 561958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 562958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 563958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 564958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 565958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup( 566958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier LookupIterator* it, Register holder_reg) { 567958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(holder()->HasNamedInterceptor()); 56813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate())); 569958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 570958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Compile the interceptor call, followed by inline code to load the 571958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // property from further up the prototype chain if the call fails. 572958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check that the maps haven't changed. 573958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1())); 574958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 575958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Preserve the receiver register explicitly whenever it is different from the 576958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // holder and it is needed should the interceptor return without any result. 577958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // The ACCESSOR case needs the receiver to be passed into C++ code, the FIELD 578958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // case might cause a miss during the prototype check. 579958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool must_perform_prototype_check = 580958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier !holder().is_identical_to(it->GetHolder<JSObject>()); 581958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool must_preserve_receiver_reg = 582958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier !receiver().is(holder_reg) && 583958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier (it->state() == LookupIterator::ACCESSOR || must_perform_prototype_check); 584958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 585958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Save necessary data before invoking an interceptor. 586958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Requires a frame to make GC aware of pushed pointers. 587958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier { 588958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FrameAndConstantPoolScope frame_scope(masm(), StackFrame::INTERNAL); 589958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (must_preserve_receiver_reg) { 590958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(receiver(), holder_reg, this->name()); 591958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 592958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(holder_reg, this->name()); 593958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 594014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch InterceptorVectorSlotPush(holder_reg); 595958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Invoke an interceptor. Note: map checks from receiver to 596958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // interceptor's holder has been compiled before (see a caller 597958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // of this method.) 598958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CompileCallLoadPropertyWithInterceptor( 599958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier masm(), receiver(), holder_reg, this->name(), holder(), 600014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Runtime::kLoadPropertyWithInterceptorOnly); 601958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 602958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check if interceptor provided a value for property. If it's 603958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // the case, return immediately. 604958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label interceptor_failed; 605958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex); 606958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(r3, scratch1()); 607958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&interceptor_failed); 608958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier frame_scope.GenerateLeaveFrame(); 609958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 610958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 611958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&interceptor_failed); 612014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch InterceptorVectorSlotPop(holder_reg); 613958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ pop(this->name()); 614958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ pop(holder_reg); 615958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (must_preserve_receiver_reg) { 616958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ pop(receiver()); 617958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 618958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Leave the internal frame. 619958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 620958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 621958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateLoadPostInterceptor(it, holder_reg); 622958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 623958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 624958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 625958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) { 626958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Call the runtime system to load the interceptor. 627958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(holder()->HasNamedInterceptor()); 62813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate())); 629958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(), 630958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier holder()); 631958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 632014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kLoadPropertyWithInterceptor); 633958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 634958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 635958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 636958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierHandle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( 637109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> callback, 638109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch LanguageMode language_mode) { 639014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register holder_reg = Frontend(name); 640958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 641958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(receiver(), holder_reg); // receiver 642014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 643014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the callback cannot leak, then push the callback directly, 644014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // otherwise wrap it in a weak cell. 64513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (callback->data()->IsUndefined(isolate()) || callback->data()->IsSmi()) { 646014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ip, Operand(callback)); 647014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 648014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<WeakCell> cell = isolate()->factory()->NewWeakCell(callback); 649014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ip, Operand(cell)); 650014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 651958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(ip); 652958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(ip, Operand(name)); 653958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(ip, value()); 654109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(Smi::FromInt(language_mode)); 655958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 656958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Do tail-call to the runtime system. 657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kStoreCallbackProperty); 658958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 659958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Return the generated code. 660bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return GetCode(kind(), name); 661958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 662958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 663958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 664958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRegister NamedStoreHandlerCompiler::value() { 665958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return StoreDescriptor::ValueRegister(); 666958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 667958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 668958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 669958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierHandle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( 670958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { 671958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label miss; 672014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IC::ICUseVector(kind())) { 673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PushVectorAndSlot(); 674014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 675014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrontendHeader(receiver(), name, &miss, DONT_RETURN_ANYTHING); 676958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 677958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Get the value from the cell. 678958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register result = StoreDescriptor::ValueRegister(); 679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell); 680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadWeakValue(result, weak_cell, &miss); 681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadP(result, FieldMemOperand(result, PropertyCell::kValueOffset)); 682958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 683958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Check for deleted property if property can actually be deleted. 684958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (is_configurable) { 685958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 686958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(result, ip); 687958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ beq(&miss); 688958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 689958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 690958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Counters* counters = isolate()->counters(); 691109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ IncrementCounter(counters->ic_named_load_global_stub(), 1, r4, r6); 692014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IC::ICUseVector(kind())) { 693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DiscardVectorAndSlot(); 694014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 695958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ret(); 696958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 697958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FrontendFooter(name, &miss); 698958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 699958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Return the generated code. 700bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return GetCode(kind(), name); 701958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 702958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 703958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 704958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#undef __ 705014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 706014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 707958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 708958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif // V8_TARGET_ARCH_ARM 709