1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2014 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_MIPS 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 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" 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/ic.h" 13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/isolate-inl.h" 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ ACCESS_MASM(masm) 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadViaGetter( 22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder, 23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int accessor_index, int expected_arguments, Register scratch) { 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------- S t a t e ------------- 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- a0 : receiver 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- a2 : name 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- ra : return address 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------------------------------- 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 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)); 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the JavaScript getter with the receiver on the stack. 39014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (map->IsJSGlobalObjectMap()) { 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Swap in the global receiver. 41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lw(scratch, 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); 43014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch receiver = scratch; 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(receiver); 46014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadAccessor(a1, holder, accessor_index, ACCESSOR_GETTER); 473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ li(a0, Operand(0)); 483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Call(masm->isolate()->builtins()->CallFunction( 493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch ConvertReceiverMode::kNotNullOrUndefined), 503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch RelocInfo::CODE_TARGET); 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we generate a global code snippet for deoptimization only, remember 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the place to continue after deoptimization. 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore context register. 583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ pop(cp); 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedStoreHandlerCompiler::GenerateStoreViaSetter( 65014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder, 66014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int accessor_index, int expected_arguments, Register scratch) { 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------- S t a t e ------------- 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- ra : return address 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------------------------------- 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Save context and value registers, so we can restore them later. 743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Push(cp, value()); 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (accessor_index >= 0) { 77014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!holder.is(scratch)); 78014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!receiver.is(scratch)); 79014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!value().is(scratch)); 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the JavaScript setter with receiver and value on the stack. 81014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (map->IsJSGlobalObjectMap()) { 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Swap in the global receiver. 83014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lw(scratch, 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); 85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch receiver = scratch; 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(receiver, value()); 88014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadAccessor(a1, holder, accessor_index, ACCESSOR_SETTER); 893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ li(a0, Operand(1)); 903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Call(masm->isolate()->builtins()->CallFunction( 913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch ConvertReceiverMode::kNotNullOrUndefined), 923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch RelocInfo::CODE_TARGET); 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we generate a global code snippet for deoptimization only, remember 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the place to continue after deoptimization. 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset()); 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We have to return the passed value, not the return value of the setter. 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore context register. 1013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Pop(cp, v0); 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid PropertyHandlerCompiler::PushVectorAndSlot(Register vector, 108958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register slot) { 109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm = this->masm(); 110f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(LoadWithVectorDescriptor::kSlot < 111f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch LoadWithVectorDescriptor::kVector); 112f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(StoreWithVectorDescriptor::kSlot < 113f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreWithVectorDescriptor::kVector); 114f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(StoreTransitionDescriptor::kSlot < 115f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreTransitionDescriptor::kVector); 116f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Push(slot, vector); 117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid PropertyHandlerCompiler::PopVectorAndSlot(Register vector, Register slot) { 121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm = this->masm(); 122f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Pop(slot, vector); 123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid PropertyHandlerCompiler::DiscardVectorAndSlot() { 127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm = this->masm(); 128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Remove vector and slot. 129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Addu(sp, sp, Operand(2 * kPointerSize)); 130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Label* miss_label, Register receiver, 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name, Register scratch0, Register scratch1) { 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(name->IsUniqueName()); 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!receiver.is(scratch0)); 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Counters* counters = masm->isolate()->counters(); 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kInterceptorOrAccessCheckNeededMask = 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Bail out if the receiver has a named interceptor or requires access checks. 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register map = scratch1; 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lbu(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ And(scratch0, scratch0, Operand(kInterceptorOrAccessCheckNeededMask)); 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(miss_label, ne, scratch0, Operand(zero_reg)); 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that receiver is a JSObject. 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lbu(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); 155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Branch(miss_label, lt, scratch0, Operand(FIRST_JS_RECEIVER_TYPE)); 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load properties array. 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register properties = scratch0; 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the properties array is a dictionary. 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(map, FieldMemOperand(properties, HeapObject::kMapOffset)); 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register tmp = properties; 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(miss_label, ne, map, Operand(tmp)); 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore the temporarily used register. 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionaryLookupStub::GenerateNegativeLookup( 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm, miss_label, &done, receiver, properties, name, scratch1); 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Generate code to check that a global property cell is empty. Create 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// the property cell at compilation time if no cell exists for the 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// property. 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PropertyHandlerCompiler::GenerateCheckPropertyCell( 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, Label* miss) { 182f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<PropertyCell> cell = JSGlobalObject::EnsureEmptyPropertyCell( 183f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch global, name, PropertyCellType::kInvalidated); 18413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Isolate* isolate = masm->isolate(); 18513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(cell->value()->IsTheHole(isolate)); 18613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell); 187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadWeakValue(scratch, weak_cell, miss); 188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lw(scratch, FieldMemOperand(scratch, PropertyCell::kValueOffset)); 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(miss, ne, scratch, Operand(at)); 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 19362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochstatic void CompileCallLoadPropertyWithInterceptor( 19462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MacroAssembler* masm, Register receiver, Register holder, Register name, 19562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Handle<JSObject> holder_obj, Runtime::FunctionId id) { 19662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK(NamedLoadHandlerCompiler::kInterceptorArgsLength == 19762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Runtime::FunctionForId(id)->nargs); 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); 200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 1); 201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 2); 202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 3); 203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(name, receiver, holder); 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(id); 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Generate call to api function. 210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid PropertyHandlerCompiler::GenerateApiAccessorCall( 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, const CallOptimization& optimization, 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> receiver_map, Register receiver, Register scratch_in, 213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool is_store, Register store_parameter, Register accessor_holder, 214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int accessor_index) { 215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!accessor_holder.is(scratch_in)); 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!receiver.is(scratch_in)); 217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(receiver); 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Write the arguments to stack frame. 219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (is_store) { 220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!receiver.is(store_parameter)); 221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!scratch_in.is(store_parameter)); 222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(store_parameter); 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(optimization.is_simple_api_call()); 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Abi for CallApiCallbackStub. 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register callee = a0; 228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register data = t0; 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register holder = a2; 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register api_function_address = a1; 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Put callee in place. 233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadAccessor(callee, accessor_holder, accessor_index, 234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch is_store ? ACCESSOR_SETTER : ACCESSOR_GETTER); 235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Put holder in place. 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallOptimization::HolderLookup holder_lookup; 238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int holder_depth = 0; 239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch optimization.LookupHolderOfExpectedType(receiver_map, &holder_lookup, 240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch &holder_depth); 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (holder_lookup) { 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CallOptimization::kHolderIsReceiver: 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(holder, receiver); 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CallOptimization::kHolderFound: 246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lw(holder, FieldMemOperand(receiver, HeapObject::kMapOffset)); 247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lw(holder, FieldMemOperand(holder, Map::kPrototypeOffset)); 248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 1; i < holder_depth; i++) { 249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lw(holder, FieldMemOperand(holder, HeapObject::kMapOffset)); 250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lw(holder, FieldMemOperand(holder, Map::kPrototypeOffset)); 251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CallOptimization::kHolderNotFound: 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate = masm->isolate(); 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool call_data_undefined = false; 261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Put call data in place. 26213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (api_call_info->data()->IsUndefined(isolate)) { 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch call_data_undefined = true; 264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(data, Heap::kUndefinedValueRootIndex); 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 266109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (optimization.is_constant_call()) { 267109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ lw(data, 268109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FieldMemOperand(callee, JSFunction::kSharedFunctionInfoOffset)); 269109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ lw(data, 270109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FieldMemOperand(data, SharedFunctionInfo::kFunctionDataOffset)); 271109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ lw(data, FieldMemOperand(data, FunctionTemplateInfo::kCallCodeOffset)); 272109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else { 273109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ lw(data, 274109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FieldMemOperand(callee, FunctionTemplateInfo::kCallCodeOffset)); 275109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lw(data, FieldMemOperand(data, CallHandlerInfo::kDataOffset)); 277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (api_call_info->fast_handler()->IsCode()) { 280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Just tail call into the fast handler if present. 281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(handle(Code::cast(api_call_info->fast_handler())), 282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo::CODE_TARGET); 283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return; 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Put api_function_address in place. 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address function_address = v8::ToCData<Address>(api_call_info->callback()); 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ApiFunction fun(function_address); 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::Type type = ExternalReference::DIRECT_API_CALL; 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference ref = ExternalReference(&fun, type, masm->isolate()); 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ li(api_function_address, Operand(ref)); 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Jump to stub. 2933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch CallApiCallbackStub stub(isolate, is_store, call_data_undefined, 294109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch !optimization.is_constant_call()); 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallStub(&stub); 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __ 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ ACCESS_MASM(masm()) 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name) { 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!label->is_unused()) { 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(label); 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ li(this->name(), Operand(name)); 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 310c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid PropertyHandlerCompiler::GenerateAccessCheck( 311c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2, 312c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label* miss, bool compare_native_contexts_only) { 313c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label done; 314c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load current native context. 315c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ lw(scratch1, NativeContextMemOperand()); 316c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load expected native context. 317c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ LoadWeakValue(scratch2, native_context_cell, miss); 318c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 319c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (!compare_native_contexts_only) { 320c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Branch(&done, eq, scratch1, Operand(scratch2)); 321c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 322c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Compare security tokens of current and expected native contexts. 323c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ lw(scratch1, ContextMemOperand(scratch1, Context::SECURITY_TOKEN_INDEX)); 324c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ lw(scratch2, ContextMemOperand(scratch2, Context::SECURITY_TOKEN_INDEX)); 325c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 326c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Branch(miss, ne, scratch1, Operand(scratch2)); 327c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 328c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ bind(&done); 329c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister PropertyHandlerCompiler::CheckPrototypes( 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object_reg, Register holder_reg, Register scratch1, 333c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Register scratch2, Handle<Name> name, Label* miss, 334014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ReturnHolder return_what) { 335014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Map> receiver_map = map(); 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Make sure there's no overlap between holder and object registers. 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !scratch2.is(scratch1)); 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 34213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Handle<Cell> validity_cell = 34313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); 34413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (!validity_cell.is_null()) { 34513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value()); 34613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ li(scratch1, Operand(validity_cell)); 34713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ lw(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset)); 34813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Branch(miss, ne, scratch1, 34913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Operand(Smi::FromInt(Map::kPrototypeChainValid))); 35013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 351014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Keep track of the current object in register reg. 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg = object_reg; 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int depth = 0; 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> current = Handle<JSObject>::null(); 357014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (receiver_map->IsJSGlobalObjectMap()) { 358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch current = isolate()->global_object(); 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 361c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Handle<Map> current_map(receiver_map->GetPrototypeChainRootMap(isolate()), 362c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch isolate()); 363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> holder_map(holder()->map()); 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Traverse the prototype chain and check the maps in the prototype chain for 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // fast and global objects or do negative lookup for normal objects. 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (!current_map.is_identical_to(holder_map)) { 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++depth; 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 36913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (current_map->IsJSGlobalObjectMap()) { 37013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), 37113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch name, scratch2, miss); 37213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } else if (current_map->is_dictionary_map()) { 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. 374c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK(name->IsUniqueName()); 375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(current.is_null() || 376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch current->property_dictionary()->FindEntry(name) == 377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionary::kNotFound); 378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 37913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (depth > 1) { 380c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Handle<WeakCell> weak_cell = 381c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Map::GetOrCreatePrototypeWeakCell(current, isolate()); 382c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ LoadWeakValue(reg, weak_cell, miss); 383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, 385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scratch2); 386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch reg = holder_reg; // From now on the object will be in holder_reg. 389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Go to the next object in the prototype chain. 390c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch current = handle(JSObject::cast(current_map->prototype())); 391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch current_map = handle(current->map()); 392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 394014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!current_map->IsJSGlobalProxyMap()); 395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Log the check depth. 397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); 398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool return_holder = return_what == RETURN_HOLDER; 40013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (return_holder && depth != 0) { 401c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Handle<WeakCell> weak_cell = 402c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Map::GetOrCreatePrototypeWeakCell(current, isolate()); 403c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ LoadWeakValue(reg, weak_cell, miss); 404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the register containing the holder. 407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return return_holder ? reg : no_reg; 408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { 412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!miss->is_unused()) { 413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label success; 414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&success); 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(miss); 416958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (IC::ICUseVector(kind())) { 417958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(kind() == Code::LOAD_IC); 418958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PopVectorAndSlot(); 419958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TailCallBuiltin(masm(), MissBuiltin(kind())); 421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&success); 422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { 427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!miss->is_unused()) { 428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label success; 429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&success); 430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateRestoreName(miss, name); 431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IC::ICUseVector(kind())) PopVectorAndSlot(); 432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TailCallBuiltin(masm(), MissBuiltin(kind())); 433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&success); 434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup( 438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LookupIterator* it, Register holder_reg) { 439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(holder()->HasNamedInterceptor()); 44013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate())); 441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compile the interceptor call, followed by inline code to load the 443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // property from further up the prototype chain if the call fails. 444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the maps haven't changed. 445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1())); 446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Preserve the receiver register explicitly whenever it is different from the 448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // holder and it is needed should the interceptor return without any result. 449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The ACCESSOR case needs the receiver to be passed into C++ code, the FIELD 450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // case might cause a miss during the prototype check. 451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool must_perform_prototype_check = 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !holder().is_identical_to(it->GetHolder<JSObject>()); 453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool must_preserve_receiver_reg = 454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !receiver().is(holder_reg) && 455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (it->state() == LookupIterator::ACCESSOR || must_perform_prototype_check); 456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save necessary data before invoking an interceptor. 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Requires a frame to make GC aware of pushed pointers. 459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope frame_scope(masm(), StackFrame::INTERNAL); 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (must_preserve_receiver_reg) { 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(receiver(), holder_reg, this->name()); 463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(holder_reg, this->name()); 465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 466958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier InterceptorVectorSlotPush(holder_reg); 467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Invoke an interceptor. Note: map checks from receiver to 468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // interceptor's holder has been compiled before (see a caller 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of this method). 470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CompileCallLoadPropertyWithInterceptor( 471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm(), receiver(), holder_reg, this->name(), holder(), 472014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Runtime::kLoadPropertyWithInterceptorOnly); 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if interceptor provided a value for property. If it's 475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the case, return immediately. 476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label interceptor_failed; 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex); 478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&interceptor_failed, eq, v0, Operand(scratch1())); 479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch frame_scope.GenerateLeaveFrame(); 480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&interceptor_failed); 483958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier InterceptorVectorSlotPop(holder_reg); 484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (must_preserve_receiver_reg) { 485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(receiver(), holder_reg, this->name()); 486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(holder_reg, this->name()); 488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Leave the internal frame. 490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateLoadPostInterceptor(it, holder_reg); 493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) { 497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the runtime system to load the interceptor. 498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(holder()->HasNamedInterceptor()); 49913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate())); 50062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 50162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); 50262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 1); 50362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 2); 50462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 3); 50562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Push(name(), receiver(), holder_reg); 50662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // See NamedLoadHandlerCompiler::InterceptorVectorSlotPop() for details. 50762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (holder_reg.is(receiver())) { 50862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Push(slot(), vector()); 50962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 51062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Push(scratch3(), scratch2()); // slot, vector 51162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 513014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kLoadPropertyWithInterceptor); 514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 516f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid NamedStoreHandlerCompiler::ZapStackArgumentsRegisterAliases() { 517f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(!StoreWithVectorDescriptor::kPassLastArgsOnStack); 518f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( 521109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> callback, 522109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch LanguageMode language_mode) { 523958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register holder_reg = Frontend(name); 524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(receiver(), holder_reg); // Receiver. 526014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the callback cannot leak, then push the callback directly, 527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // otherwise wrap it in a weak cell. 52813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (callback->data()->IsUndefined(isolate()) || callback->data()->IsSmi()) { 529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(at, Operand(callback)); 530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<WeakCell> cell = isolate()->factory()->NewWeakCell(callback); 532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ li(at, Operand(cell)); 533014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(at); 535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ li(at, Operand(name)); 536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(at, value()); 537109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(Smi::FromInt(language_mode)); 538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do tail-call to the runtime system. 540014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kStoreCallbackProperty); 541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the generated code. 543bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return GetCode(kind(), name); 544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister NamedStoreHandlerCompiler::value() { 548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return StoreDescriptor::ValueRegister(); 549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( 553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { 554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label miss; 555958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (IC::ICUseVector(kind())) { 556958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PushVectorAndSlot(); 557958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrontendHeader(receiver(), name, &miss, DONT_RETURN_ANYTHING); 560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the value from the cell. 562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = StoreDescriptor::ValueRegister(); 563958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell); 564958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadWeakValue(result, weak_cell, &miss); 565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lw(result, FieldMemOperand(result, PropertyCell::kValueOffset)); 566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for deleted property if property can actually be deleted. 568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (is_configurable) { 569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&miss, eq, result, Operand(at)); 571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Counters* counters = isolate()->counters(); 574109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ IncrementCounter(counters->ic_named_load_global_stub(), 1, a1, a3); 575958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (IC::ICUseVector(kind())) { 576958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DiscardVectorAndSlot(); 577958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(USE_DELAY_SLOT); 579f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Move(v0, result); // Ensure the stub returns correct value. 580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrontendFooter(name, &miss); 582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the generated code. 584bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return GetCode(kind(), name); 585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __ 589014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 590014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // V8_TARGET_ARCH_MIPS 593