handler-compiler-arm64.cc revision 958fae7ec3f466955f8e5b50fa5b8d38b9e91675
1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2014 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h" 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_ARM64 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/call-optimization.h" 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/handler-compiler.h" 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/ic.h" 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ ACCESS_MASM(masm) 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 18958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid PropertyHandlerCompiler::PushVectorAndSlot(Register vector, 19958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register slot) { 20958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm = this->masm(); 21958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(vector); 22958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Push(slot); 23958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 24958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 25958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 26958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid PropertyHandlerCompiler::PopVectorAndSlot(Register vector, Register slot) { 27958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm = this->masm(); 28958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Pop(slot); 29958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Pop(vector); 30958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 31958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 32958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 33958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid PropertyHandlerCompiler::DiscardVectorAndSlot() { 34958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm = this->masm(); 35958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Remove vector and slot. 36958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Drop(2); 37958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 38958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Label* miss_label, Register receiver, 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name, Register scratch0, Register scratch1) { 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!AreAliased(receiver, scratch0, scratch1)); 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(name->IsUniqueName()); 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Counters* counters = masm->isolate()->counters(); 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kInterceptorOrAccessCheckNeededMask = 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Bail out if the receiver has a named interceptor or requires access checks. 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register map = scratch1; 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrb(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Tst(scratch0, kInterceptorOrAccessCheckNeededMask); 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(ne, miss_label); 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that receiver is a JSObject. 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldrb(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(scratch0, FIRST_SPEC_OBJECT_TYPE); 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(lt, miss_label); 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load properties array. 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register properties = scratch0; 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the properties array is a dictionary. 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(map, FieldMemOperand(properties, HeapObject::kMapOffset)); 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotRoot(map, Heap::kHashTableMapRootIndex, miss_label); 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionaryLookupStub::GenerateNegativeLookup( 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm, miss_label, &done, receiver, properties, name, scratch1); 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&done); 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype( 81958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, int index, Register result, Label* miss) { 82958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ldr(result, GlobalObjectMemOperand()); 83958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ldr(result, FieldMemOperand(result, GlobalObject::kNativeContextOffset)); 84958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ldr(result, ContextMemOperand(result, index)); 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load its initial map. The global functions all have initial maps. 86958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ldr(result, 87958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldMemOperand(result, JSFunction::kPrototypeOrInitialMapOffset)); 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the prototype from the initial map. 89958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ldr(result, FieldMemOperand(result, Map::kPrototypeOffset)); 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype( 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Register receiver, Register scratch1, 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2, Label* miss_label) { 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TryGetFunctionPrototype can't put the result directly in x0 because the 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 3 inputs registers can't alias and we call this function from 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // LoadIC::GenerateFunctionPrototype, where receiver is x0. So we explicitly 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // move the result in x0. 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(x0, scratch1); 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Generate code to check that a global property cell is empty. Create 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// the property cell at compilation time if no cell exists for the 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// property. 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PropertyHandlerCompiler::GenerateCheckPropertyCell( 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, Label* miss) { 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Cell> cell = JSGlobalObject::EnsurePropertyCell(global, name); 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(cell->value()->IsTheHole()); 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(scratch, Operand(cell)); 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotRoot(scratch, Heap::kTheHoleValueRootIndex, miss); 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void PushInterceptorArguments(MacroAssembler* masm, Register receiver, 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register holder, Register name, 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> holder_obj) { 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1); 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2); 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3); 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 4); 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(name); 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!masm->isolate()->heap()->InNewSpace(*interceptor)); 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch = name; 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(scratch, Operand(interceptor)); 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(scratch, receiver, holder); 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CompileCallLoadPropertyWithInterceptor( 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Register receiver, Register holder, Register name, 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> holder_obj, IC::UtilityId id) { 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PushInterceptorArguments(masm, receiver, holder, name, holder_obj); 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallExternalReference(ExternalReference(IC_Utility(id), masm->isolate()), 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NamedLoadHandlerCompiler::kInterceptorArgsLength); 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Generate call to api function. 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PropertyHandlerCompiler::GenerateFastApiCall( 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, const CallOptimization& optimization, 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> receiver_map, Register receiver, Register scratch, 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_store, int argc, Register* values) { 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!AreAliased(receiver, scratch)); 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler::PushPopQueue queue(masm); 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch queue.Queue(receiver); 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Write the arguments to the stack frame. 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < argc; i++) { 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register arg = values[argc - 1 - i]; 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!AreAliased(receiver, scratch, arg)); 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch queue.Queue(arg); 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch queue.PushQueued(); 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(optimization.is_simple_api_call()); 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Abi for CallApiFunctionStub. 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register callee = x0; 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register call_data = x4; 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register holder = x2; 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register api_function_address = x1; 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Put holder in place. 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallOptimization::HolderLookup holder_lookup; 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> api_holder = 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch optimization.LookupHolderOfExpectedType(receiver_map, &holder_lookup); 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (holder_lookup) { 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CallOptimization::kHolderIsReceiver: 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(holder, receiver); 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CallOptimization::kHolderFound: 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadObject(holder, api_holder); 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CallOptimization::kHolderNotFound: 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate = masm->isolate(); 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSFunction> function = optimization.constant_function(); 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> call_data_obj(api_call_info->data(), isolate); 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Put callee in place. 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadObject(callee, function); 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool call_data_undefined = false; 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Put call_data in place. 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (isolate->heap()->InNewSpace(*call_data_obj)) { 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadObject(call_data, api_call_info); 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(call_data, FieldMemOperand(call_data, CallHandlerInfo::kDataOffset)); 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (call_data_obj->IsUndefined()) { 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch call_data_undefined = true; 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(call_data, Heap::kUndefinedValueRootIndex); 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadObject(call_data, call_data_obj); 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Put api_function_address in place. 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address function_address = v8::ToCData<Address>(api_call_info->callback()); 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ApiFunction fun(function_address); 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference ref = ExternalReference( 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &fun, ExternalReference::DIRECT_API_CALL, masm->isolate()); 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(api_function_address, ref); 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Jump to stub. 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc); 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallStub(&stub); 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedStoreHandlerCompiler::GenerateStoreViaSetter( 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Handle<HeapType> type, Register receiver, 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSFunction> setter) { 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------- S t a t e ------------- 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- lr : return address 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------------------------------- 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label miss; 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save value register, so we can restore it later. 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(value()); 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!setter.is_null()) { 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the JavaScript setter with receiver and value on the stack. 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Swap in the global receiver. 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(receiver, 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(receiver, value()); 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ParameterCount actual(1); 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ParameterCount expected(setter); 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeFunction(setter, expected, actual, CALL_FUNCTION, 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NullCallWrapper()); 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we generate a global code snippet for deoptimization only, remember 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the place to continue after deoptimization. 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset()); 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We have to return the passed value, not the return value of the setter. 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(x0); 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore context register. 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadViaGetter( 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Handle<HeapType> type, Register receiver, 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSFunction> getter) { 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!getter.is_null()) { 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the JavaScript getter with the receiver on the stack. 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Swap in the global receiver. 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(receiver, 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(receiver); 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ParameterCount actual(0); 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ParameterCount expected(getter); 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeFunction(getter, expected, actual, CALL_FUNCTION, 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NullCallWrapper()); 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we generate a global code snippet for deoptimization only, remember 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the place to continue after deoptimization. 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore context register. 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedStoreHandlerCompiler::GenerateSlow(MacroAssembler* masm) { 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push receiver, name and value for runtime call. 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(), 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StoreDescriptor::ValueRegister()); 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The slow case calls into the runtime to complete the store without causing 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // an IC miss that would otherwise cause a transition to the generic stub. 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference ref = 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference(IC_Utility(IC::kStoreIC_Slow), masm->isolate()); 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallExternalReference(ref, 3, 1); 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) { 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("ElementHandlerCompiler::GenerateStoreSlow"); 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push receiver, key and value for runtime call. 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(), 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StoreDescriptor::ValueRegister()); 314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The slow case calls into the runtime to complete the store without causing 316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // an IC miss that would otherwise cause a transition to the generic stub. 317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference ref = 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference(IC_Utility(IC::kKeyedStoreIC_Slow), masm->isolate()); 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallExternalReference(ref, 3, 1); 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __ 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ ACCESS_MASM(masm()) 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label miss; 330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (IC::ICUseVector(kind())) { 331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PushVectorAndSlot(); 332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrontendHeader(receiver(), name, &miss); 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the value from the cell. 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = StoreDescriptor::ValueRegister(); 337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell); 338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadWeakValue(result, weak_cell, &miss); 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(result, FieldMemOperand(result, Cell::kValueOffset)); 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for deleted property if property can actually be deleted. 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (is_configurable) { 343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfRoot(result, Heap::kTheHoleValueRootIndex, &miss); 344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Counters* counters = isolate()->counters(); 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IncrementCounter(counters->named_load_global_stub(), 1, x1, x3); 348958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (IC::ICUseVector(kind())) { 349958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DiscardVectorAndSlot(); 350958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrontendFooter(name, &miss); 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the generated code. 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return GetCode(kind(), Code::NORMAL, name); 357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name) { 362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label miss; 363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("NamedStoreHandlerCompiler::CompileStoreInterceptor"); 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(receiver(), this->name(), value()); 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do tail-call to the runtime system. 369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference store_ic_property = ExternalReference( 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); 371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallExternalReference(store_ic_property, 3, 1); 372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the generated code. 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return GetCode(kind(), Code::FAST, name); 375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister NamedStoreHandlerCompiler::value() { 379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return StoreDescriptor::ValueRegister(); 380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, 384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name) { 385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!label->is_unused()) { 386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(label); 387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(this->name(), Operand(name)); 388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 392958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) { 393958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Mov(this->name(), Operand(name)); 394958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 397958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition, 398958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch, 399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label* miss) { 400958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<WeakCell> cell = Map::WeakCellForMap(transition); 401958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register map_reg = StoreTransitionDescriptor::MapRegister(); 402958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!map_reg.is(scratch)); 403958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadWeakValue(map_reg, cell, miss); 404958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (transition->CanBeDeprecated()) { 405958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ldrsw(scratch, FieldMemOperand(map_reg, Map::kBitField3Offset)); 406958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ TestAndBranchIfAnySet(scratch, Map::Deprecated::kMask, miss); 407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 408958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 411958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::GenerateConstantCheck(Register map_reg, 412958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int descriptor, 413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register value_reg, 414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch, 415958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label* miss_label) { 416958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!map_reg.is(scratch)); 417958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!map_reg.is(value_reg)); 418958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!value_reg.is(scratch)); 419958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadInstanceDescriptors(map_reg, scratch); 420958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ldr(scratch, 421958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldMemOperand(scratch, DescriptorArray::GetValueOffset(descriptor))); 422958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Cmp(value_reg, scratch); 423958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ B(ne, miss_label); 424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 427958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::GenerateFieldTypeChecks(HeapType* field_type, 428958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register value_reg, 429958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label* miss_label) { 430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(value_reg, miss_label); 431958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier HeapType::Iterator<Map> it = field_type->Classes(); 432958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!it.Done()) { 433958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ldr(scratch1(), FieldMemOperand(value_reg, HeapObject::kMapOffset)); 434958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label do_store; 435958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier while (true) { 436958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CompareMap(scratch1(), it.Current()); 437958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier it.Advance(); 438958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (it.Done()) { 439958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ B(ne, miss_label); 440958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 441958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 442958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ B(eq, &do_store); 443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 444958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Bind(&do_store); 445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister PropertyHandlerCompiler::CheckPrototypes( 450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object_reg, Register holder_reg, Register scratch1, 451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2, Handle<Name> name, Label* miss, 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrototypeCheckType check) { 453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); 454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // object_reg and holder_reg registers can alias. 456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!AreAliased(object_reg, scratch1, scratch2)); 457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!AreAliased(holder_reg, scratch1, scratch2)); 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Keep track of the current object in register reg. 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg = object_reg; 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int depth = 0; 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> current = Handle<JSObject>::null(); 464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (type()->IsConstant()) { 465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch current = Handle<JSObject>::cast(type()->AsConstant()->Value()); 466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> prototype = Handle<JSObject>::null(); 468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> current_map = receiver_map; 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> holder_map(holder()->map()); 470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Traverse the prototype chain and check the maps in the prototype chain for 471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // fast and global objects or do negative lookup for normal objects. 472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (!current_map.is_identical_to(holder_map)) { 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++depth; 474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Only global objects and objects that do not require access 476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // checks are allowed in stubs. 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(current_map->IsJSGlobalProxyMap() || 478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !current_map->is_access_check_needed()); 479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch prototype = handle(JSObject::cast(current_map->prototype())); 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (current_map->is_dictionary_map() && 482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !current_map->IsJSGlobalObjectMap()) { 483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. 484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!name->IsUniqueName()) { 485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(name->IsString()); 486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name = factory()->InternalizeString(Handle<String>::cast(name)); 487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(current.is_null() || (current->property_dictionary()->FindEntry( 489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name) == NameDictionary::kNotFound)); 490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scratch2); 493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); 495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg = holder_reg; // From now on the object will be in holder_reg. 496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); 497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register map_reg = scratch1; 499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); 500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (depth != 1 || check == CHECK_ALL_MAPS) { 502958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<WeakCell> cell = Map::WeakCellForMap(current_map); 503958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CmpWeakValue(map_reg, cell, scratch2); 504958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ B(ne, miss); 505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check access rights to the global object. This has to happen after 508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the map check so that we know that the object is actually a global 509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // object. 510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This allows us to install generated handlers for accesses to the 511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // global proxy (as opposed to using slow ICs). See corresponding code 512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // in LookupForRead(). 513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (current_map->IsJSGlobalProxyMap()) { 514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UseScratchRegisterScope temps(masm()); 515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CheckAccessGlobalProxy(reg, scratch2, temps.AcquireX(), miss); 516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (current_map->IsJSGlobalObjectMap()) { 517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), 518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name, scratch2, miss); 519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg = holder_reg; // From now on the object will be in holder_reg. 522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 523958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ldr(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); 524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Go to the next object in the prototype chain. 527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch current = prototype; 528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch current_map = handle(current->map()); 529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Log the check depth. 532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); 533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check the holder map. 535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (depth != 0 || check == CHECK_ALL_MAPS) { 536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check the holder map. 537958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); 538958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<WeakCell> cell = Map::WeakCellForMap(current_map); 539958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ CmpWeakValue(scratch1, cell, scratch2); 540958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ B(ne, miss); 541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform security check for access to the global object. 544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(current_map->IsJSGlobalProxyMap() || 545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !current_map->is_access_check_needed()); 546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (current_map->IsJSGlobalProxyMap()) { 547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); 548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the register containing the holder. 551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return reg; 552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { 556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!miss->is_unused()) { 557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label success; 558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&success); 559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(miss); 561958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (IC::ICUseVector(kind())) { 562958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(kind() == Code::LOAD_IC); 563958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PopVectorAndSlot(); 564958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TailCallBuiltin(masm(), MissBuiltin(kind())); 566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&success); 568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { 573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!miss->is_unused()) { 574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label success; 575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ B(&success); 576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateRestoreName(miss, name); 578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TailCallBuiltin(masm(), MissBuiltin(kind())); 579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&success); 581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { 586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the constant value. 587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadObject(x0, value); 588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadCallback( 593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg, Handle<ExecutableAccessorInfo> callback) { 594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!AreAliased(scratch2(), scratch3(), scratch4(), reg)); 595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Build ExecutableAccessorInfo::args_ list on the stack and push property 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // name below the exit frame to make GC aware of them and store pointers to 598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // them. 599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); 600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); 601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); 602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); 603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); 604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); 605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6); 606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(receiver()); 608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (heap()->InNewSpace(callback->data())) { 610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(scratch3(), Operand(callback)); 611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ldr(scratch3(), 612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldMemOperand(scratch3(), ExecutableAccessorInfo::kDataOffset)); 613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(scratch3(), Operand(Handle<Object>(callback->data(), isolate()))); 615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(scratch4(), Heap::kUndefinedValueRootIndex); 617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(scratch2(), Operand(ExternalReference::isolate_address(isolate()))); 618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(scratch3(), scratch4(), scratch4(), scratch2(), reg, name()); 619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register args_addr = scratch2(); 621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Add(args_addr, __ StackPointer(), kPointerSize); 622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Stack at this point: 624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // sp[40] callback data 625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // sp[32] undefined 626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // sp[24] undefined 627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // sp[16] isolate 628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // args_addr -> sp[8] reg 629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // sp[0] name 630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Abi for CallApiGetter. 632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register getter_address_reg = x2; 633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Set up the call. 635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address getter_address = v8::ToCData<Address>(callback->getter()); 636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ApiFunction fun(getter_address); 637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; 638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference ref = ExternalReference(&fun, type, isolate()); 639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(getter_address_reg, ref); 640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallApiGetterStub stub(isolate()); 642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallStub(&stub); 643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup( 647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LookupIterator* it, Register holder_reg) { 648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!AreAliased(receiver(), this->name(), scratch1(), scratch2(), 649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scratch3())); 650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(holder()->HasNamedInterceptor()); 651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); 652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compile the interceptor call, followed by inline code to load the 654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // property from further up the prototype chain if the call fails. 655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the maps haven't changed. 656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1())); 657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Preserve the receiver register explicitly whenever it is different from the 659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // holder and it is needed should the interceptor return without any result. 660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The ACCESSOR case needs the receiver to be passed into C++ code, the FIELD 661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // case might cause a miss during the prototype check. 662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool must_perform_prototype_check = 663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !holder().is_identical_to(it->GetHolder<JSObject>()); 664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool must_preserve_receiver_reg = 665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !receiver().is(holder_reg) && 666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (it->state() == LookupIterator::ACCESSOR || must_perform_prototype_check); 667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save necessary data before invoking an interceptor. 669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Requires a frame to make GC aware of pushed pointers. 670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope frame_scope(masm(), StackFrame::INTERNAL); 672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (must_preserve_receiver_reg) { 673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(receiver(), holder_reg, this->name()); 674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(holder_reg, this->name()); 676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 677958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier InterceptorVectorSlotPush(holder_reg); 678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Invoke an interceptor. Note: map checks from receiver to 679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // interceptor's holder has been compiled before (see a caller 680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of this method.) 681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CompileCallLoadPropertyWithInterceptor( 682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm(), receiver(), holder_reg, this->name(), holder(), 683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IC::kLoadPropertyWithInterceptorOnly); 684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if interceptor provided a value for property. If it's 686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the case, return immediately. 687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label interceptor_failed; 688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfRoot(x0, Heap::kNoInterceptorResultSentinelRootIndex, 689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &interceptor_failed); 690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch frame_scope.GenerateLeaveFrame(); 691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Bind(&interceptor_failed); 694958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier InterceptorVectorSlotPop(holder_reg); 695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (must_preserve_receiver_reg) { 696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(this->name(), holder_reg, receiver()); 697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(this->name(), holder_reg); 699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Leave the internal frame. 701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateLoadPostInterceptor(it, holder_reg); 704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) { 708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the runtime system to load the interceptor. 709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(holder()->HasNamedInterceptor()); 710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); 711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(), 712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch holder()); 713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference ref = ExternalReference( 715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IC_Utility(IC::kLoadPropertyWithInterceptor), isolate()); 716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallExternalReference( 717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); 718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( 722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> object, Handle<Name> name, 723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<ExecutableAccessorInfo> callback) { 724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASM_LOCATION("NamedStoreHandlerCompiler::CompileStoreCallback"); 725958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register holder_reg = Frontend(name); 726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Stub never generated for non-global objects that require access checks. 728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(holder()->IsJSGlobalProxy() || !holder()->IsAccessCheckNeeded()); 729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // receiver() and holder_reg can alias. 731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!AreAliased(receiver(), scratch1(), scratch2(), value())); 732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!AreAliased(holder_reg, scratch1(), scratch2(), value())); 733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(scratch1(), Operand(callback)); 734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mov(scratch2(), Operand(name)); 735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(receiver(), holder_reg, scratch1(), scratch2(), value()); 736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do tail-call to the runtime system. 738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference store_callback_property = 739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); 740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallExternalReference(store_callback_property, 5, 1); 741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the generated code. 743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return GetCode(kind(), Code::FAST, name); 744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __ 748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace v8::internal 750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // V8_TARGET_ARCH_IA32 752