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_IA32 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 { 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Save context register 283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ push(esi); 293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (accessor_index >= 0) { 31014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!holder.is(scratch)); 32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!receiver.is(scratch)); 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the JavaScript getter with the receiver on the stack. 34014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (map->IsJSGlobalObjectMap()) { 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Swap in the global receiver. 36014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(scratch, 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); 38014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch receiver = scratch; 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(receiver); 41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadAccessor(edi, holder, accessor_index, ACCESSOR_GETTER); 423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Set(eax, 0); 433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Call(masm->isolate()->builtins()->CallFunction( 443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch ConvertReceiverMode::kNotNullOrUndefined), 453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch RelocInfo::CODE_TARGET); 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we generate a global code snippet for deoptimization only, remember 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the place to continue after deoptimization. 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore context register. 533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ pop(esi); 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 59958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid PropertyHandlerCompiler::PushVectorAndSlot(Register vector, 60958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register slot) { 61958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm = this->masm(); 62f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(LoadWithVectorDescriptor::kSlot < 63f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch LoadWithVectorDescriptor::kVector); 64f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(StoreWithVectorDescriptor::kSlot < 65f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreWithVectorDescriptor::kVector); 66f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(StoreTransitionDescriptor::kSlot < 67f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreTransitionDescriptor::kVector); 68958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ push(slot); 69f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ push(vector); 70958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 71958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 72958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 73958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid PropertyHandlerCompiler::PopVectorAndSlot(Register vector, Register slot) { 74958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm = this->masm(); 75958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ pop(vector); 76f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ pop(slot); 77958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 78958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 79958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 80958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid PropertyHandlerCompiler::DiscardVectorAndSlot() { 81958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm = this->masm(); 82958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Remove vector and slot. 83958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ add(esp, Immediate(2 * kPointerSize)); 84958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 85958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 86f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid PropertyHandlerCompiler::PushReturnAddress(Register tmp) { 87f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch MacroAssembler* masm = this->masm(); 88f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ push(tmp); 89f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 90f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 91f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid PropertyHandlerCompiler::PopReturnAddress(Register tmp) { 92f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch MacroAssembler* masm = this->masm(); 93f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ pop(tmp); 94f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 95958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Label* miss_label, Register receiver, 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name, Register scratch0, Register scratch1) { 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(name->IsUniqueName()); 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!receiver.is(scratch0)); 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Counters* counters = masm->isolate()->counters(); 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IncrementCounter(counters->negative_lookups(), 1); 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IncrementCounter(counters->negative_lookups_miss(), 1); 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch0, FieldOperand(receiver, HeapObject::kMapOffset)); 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kInterceptorOrAccessCheckNeededMask = 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Bail out if the receiver has a named interceptor or requires access checks. 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test_b(FieldOperand(scratch0, Map::kBitFieldOffset), 1123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Immediate(kInterceptorOrAccessCheckNeededMask)); 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, miss_label); 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that receiver is a JSObject. 116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpInstanceType(scratch0, FIRST_JS_RECEIVER_TYPE); 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(below, miss_label); 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load properties array. 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register properties = scratch0; 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the properties array is a dictionary. 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(FieldOperand(properties, HeapObject::kMapOffset), 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(masm->isolate()->factory()->hash_table_map())); 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, miss_label); 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionaryLookupStub::GenerateNegativeLookup(masm, miss_label, &done, 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch properties, name, scratch1); 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ DecrementCounter(counters->negative_lookups_miss(), 1); 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype( 137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier MacroAssembler* masm, int index, Register result, Label* miss) { 138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadGlobalFunction(index, result); 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load its initial map. The global functions all have initial maps. 140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(result, 141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldOperand(result, JSFunction::kPrototypeOrInitialMapOffset)); 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the prototype from the initial map. 143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(result, FieldOperand(result, Map::kPrototypeOffset)); 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype( 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Register receiver, Register scratch1, 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2, Label* miss_label) { 150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // TODO(mvstanton): This isn't used on ia32. Move all the other 151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // platform implementations into a code stub so this method can be removed. 152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch UNREACHABLE(); 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Generate call to api function. 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// This function uses push() to generate smaller, faster code than 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// the version above. It is an optimization that should will be removed 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// when api call ICs are generated in hydrogen. 160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid PropertyHandlerCompiler::GenerateApiAccessorCall( 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, const CallOptimization& optimization, 162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Map> receiver_map, Register receiver, Register scratch, 163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool is_store, Register store_parameter, Register accessor_holder, 164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int accessor_index) { 165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!accessor_holder.is(scratch)); 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Copy return value. 167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ pop(scratch); 168f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 169f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (is_store) { 170f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Discard stack arguments. 171f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ add(esp, Immediate(StoreWithVectorDescriptor::kStackArgumentsCount * 172f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch kPointerSize)); 173f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 174f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Write the receiver and arguments to stack frame. 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(receiver); 176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (is_store) { 177f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DCHECK(!AreAliased(receiver, scratch, store_parameter)); 178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(store_parameter); 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(scratch); 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Stack now matches JSFunction abi. 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(optimization.is_simple_api_call()); 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Abi for CallApiCallbackStub. 185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register callee = edi; 186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register data = ebx; 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register holder = ecx; 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register api_function_address = edx; 189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch scratch = no_reg; 190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Put callee in place. 192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadAccessor(callee, accessor_holder, accessor_index, 193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch is_store ? ACCESSOR_SETTER : ACCESSOR_GETTER); 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Put holder in place. 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallOptimization::HolderLookup holder_lookup; 197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int holder_depth = 0; 198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch optimization.LookupHolderOfExpectedType(receiver_map, &holder_lookup, 199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch &holder_depth); 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (holder_lookup) { 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CallOptimization::kHolderIsReceiver: 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(holder, receiver); 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CallOptimization::kHolderFound: 205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(holder, FieldOperand(receiver, HeapObject::kMapOffset)); 206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(holder, FieldOperand(holder, Map::kPrototypeOffset)); 207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 1; i < holder_depth; i++) { 208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(holder, FieldOperand(holder, HeapObject::kMapOffset)); 209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(holder, FieldOperand(holder, Map::kPrototypeOffset)); 210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CallOptimization::kHolderNotFound: 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate = masm->isolate(); 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool call_data_undefined = false; 220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Put call data in place. 22113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (api_call_info->data()->IsUndefined(isolate)) { 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch call_data_undefined = true; 223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(data, Immediate(isolate->factory()->undefined_value())); 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 225109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (optimization.is_constant_call()) { 226109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(data, FieldOperand(callee, JSFunction::kSharedFunctionInfoOffset)); 227109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(data, FieldOperand(data, SharedFunctionInfo::kFunctionDataOffset)); 228109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(data, FieldOperand(data, FunctionTemplateInfo::kCallCodeOffset)); 229109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else { 230109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(data, FieldOperand(callee, FunctionTemplateInfo::kCallCodeOffset)); 231109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(data, FieldOperand(data, CallHandlerInfo::kDataOffset)); 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (api_call_info->fast_handler()->IsCode()) { 236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Just tail call into the code. 237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(handle(Code::cast(api_call_info->fast_handler())), 238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo::CODE_TARGET); 239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return; 240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Put api_function_address in place. 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address function_address = v8::ToCData<Address>(api_call_info->callback()); 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(api_function_address, Immediate(function_address)); 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Jump to stub. 2463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch CallApiCallbackStub stub(isolate, is_store, call_data_undefined, 247109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch !optimization.is_constant_call()); 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallStub(&stub); 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Generate code to check that a global property cell is empty. Create 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// the property cell at compilation time if no cell exists for the 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// property. 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PropertyHandlerCompiler::GenerateCheckPropertyCell( 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, Label* miss) { 258f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<PropertyCell> cell = JSGlobalObject::EnsureEmptyPropertyCell( 259f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch global, name, PropertyCellType::kInvalidated); 26013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Isolate* isolate = masm->isolate(); 26113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(cell->value()->IsTheHole(isolate)); 26213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell); 263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadWeakValue(scratch, weak_cell, miss); 264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), 26513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Immediate(isolate->factory()->the_hole_value())); 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, miss); 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedStoreHandlerCompiler::GenerateStoreViaSetter( 271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder, 272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int accessor_index, int expected_arguments, Register scratch) { 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------- S t a t e ------------- 274f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // -- esp[12] : value 275f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // -- esp[8] : slot 276f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // -- esp[4] : vector 277f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // -- esp[0] : return address 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------------------------------- 279f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ LoadParameterFromStack<Descriptor>(value(), Descriptor::kValue); 280f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Save context register 2853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ push(esi); 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save value register, so we can restore it later. 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(value()); 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (accessor_index >= 0) { 290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!holder.is(scratch)); 291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!receiver.is(scratch)); 292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!value().is(scratch)); 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the JavaScript setter with receiver and value on the stack. 294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (map->IsJSGlobalObjectMap()) { 295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(scratch, 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); 297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch receiver = scratch; 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(receiver); 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(value()); 301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadAccessor(edi, holder, accessor_index, ACCESSOR_SETTER); 3023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Set(eax, 1); 3033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ Call(masm->isolate()->builtins()->CallFunction( 3043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch ConvertReceiverMode::kNotNullOrUndefined), 3053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch RelocInfo::CODE_TARGET); 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we generate a global code snippet for deoptimization only, remember 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the place to continue after deoptimization. 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset()); 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We have to return the passed value, not the return value of the setter. 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(eax); 314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore context register. 3153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ pop(esi); 316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 317f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (accessor_index >= 0) { 318f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ ret(StoreWithVectorDescriptor::kStackArgumentsCount * kPointerSize); 319f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 320f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // If we generate a global code snippet for deoptimization only, don't try 321f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // to drop stack arguments for the StoreIC because they are not a part of 322f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // expression stack and deoptimizer does not reconstruct them. 323f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ ret(0); 324f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void PushInterceptorArguments(MacroAssembler* masm, Register receiver, 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register holder, Register name, 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> holder_obj) { 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); 332014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 1); 333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 2); 334014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 3); 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(name); 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(receiver); 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(holder); 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CompileCallLoadPropertyWithInterceptor( 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Register receiver, Register holder, Register name, 343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<JSObject> holder_obj, Runtime::FunctionId id) { 344014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(NamedLoadHandlerCompiler::kInterceptorArgsLength == 345014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Runtime::FunctionForId(id)->nargs); 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PushInterceptorArguments(masm, receiver, holder, name, holder_obj); 347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(id); 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __ 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ ACCESS_MASM(masm()) 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name) { 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!label->is_unused()) { 357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(label); 358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(this->name(), Immediate(name)); 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 363958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) { 364958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(this->name(), Immediate(name)); 365958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 368958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition, 369014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register map_reg, 370958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch, 371958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label* miss) { 372958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<WeakCell> cell = Map::WeakCellForMap(transition); 373958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!map_reg.is(scratch)); 374958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadWeakValue(map_reg, cell, miss); 375958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (transition->CanBeDeprecated()) { 376958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(scratch, FieldOperand(map_reg, Map::kBitField3Offset)); 377958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ and_(scratch, Immediate(Map::Deprecated::kMask)); 378958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ j(not_zero, miss); 379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 380958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 383958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::GenerateConstantCheck(Register map_reg, 384958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int descriptor, 385958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register value_reg, 386958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register scratch, 387958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label* miss_label) { 388958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!map_reg.is(scratch)); 389958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!map_reg.is(value_reg)); 390958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!value_reg.is(scratch)); 391958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadInstanceDescriptors(map_reg, scratch); 392958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(scratch, 393958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldOperand(scratch, DescriptorArray::GetValueOffset(descriptor))); 394958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ cmp(value_reg, scratch); 395958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ j(not_equal, miss_label); 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 398109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid NamedStoreHandlerCompiler::GenerateFieldTypeChecks(FieldType* field_type, 399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register value_reg, 400958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label* miss_label) { 401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register map_reg = scratch1(); 402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register scratch = scratch2(); 403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!value_reg.is(map_reg)); 404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!value_reg.is(scratch)); 405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(value_reg, miss_label); 406109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (field_type->IsClass()) { 407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(map_reg, FieldOperand(value_reg, HeapObject::kMapOffset)); 408109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CmpWeakValue(map_reg, Map::WeakCellForMap(field_type->AsClass()), 409109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch scratch); 410109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(not_equal, miss_label); 411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 414c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid PropertyHandlerCompiler::GenerateAccessCheck( 415c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2, 416c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label* miss, bool compare_native_contexts_only) { 417c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Label done; 418c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load current native context. 419c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ mov(scratch1, NativeContextOperand()); 420c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Load expected native context. 421c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ LoadWeakValue(scratch2, native_context_cell, miss); 422c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ cmp(scratch1, scratch2); 423c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 424c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (!compare_native_contexts_only) { 425c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ j(equal, &done); 426c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 427c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Compare security tokens of current and expected native contexts. 428c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ mov(scratch1, ContextOperand(scratch1, Context::SECURITY_TOKEN_INDEX)); 429c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ mov(scratch2, ContextOperand(scratch2, Context::SECURITY_TOKEN_INDEX)); 430c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ cmp(scratch1, scratch2); 431c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 432c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ j(not_equal, miss); 433c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 434c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ bind(&done); 435c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister PropertyHandlerCompiler::CheckPrototypes( 438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object_reg, Register holder_reg, Register scratch1, 439c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Register scratch2, Handle<Name> name, Label* miss, 440014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ReturnHolder return_what) { 441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Map> receiver_map = map(); 442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Make sure there's no overlap between holder and object registers. 444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && 446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !scratch2.is(scratch1)); 447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 44813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Handle<Cell> validity_cell = 44913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); 45013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (!validity_cell.is_null()) { 45113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value()); 45213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Operand::ForCell(...) points to the cell's payload! 45313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ cmp(Operand::ForCell(validity_cell), 45413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Immediate(Smi::FromInt(Map::kPrototypeChainValid))); 45513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ j(not_equal, miss); 45613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 457014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Keep track of the current object in register reg. 459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg = object_reg; 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int depth = 0; 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> current = Handle<JSObject>::null(); 463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (receiver_map->IsJSGlobalObjectMap()) { 464014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch current = isolate()->global_object(); 465014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 466014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 467c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Handle<Map> current_map(receiver_map->GetPrototypeChainRootMap(isolate()), 468c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch isolate()); 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 47513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (current_map->IsJSGlobalObjectMap()) { 47613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), 47713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch name, scratch2, miss); 47813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } else if (current_map->is_dictionary_map()) { 479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. 480c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK(name->IsUniqueName()); 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(current.is_null() || 482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch current->property_dictionary()->FindEntry(name) == 483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionary::kNotFound); 484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 48513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (depth > 1) { 486c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Handle<WeakCell> weak_cell = 487c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Map::GetOrCreatePrototypeWeakCell(current, isolate()); 488c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ LoadWeakValue(reg, weak_cell, miss); 489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scratch2); 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 494014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch reg = holder_reg; // From now on the object will be in holder_reg. 495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Go to the next object in the prototype chain. 496c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch current = handle(JSObject::cast(current_map->prototype())); 497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch current_map = handle(current->map()); 498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 500014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!current_map->IsJSGlobalProxyMap()); 501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Log the check depth. 503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); 504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 505014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool return_holder = return_what == RETURN_HOLDER; 50613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (return_holder && depth != 0) { 507c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Handle<WeakCell> weak_cell = 508c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Map::GetOrCreatePrototypeWeakCell(current, isolate()); 509c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ LoadWeakValue(reg, weak_cell, miss); 510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the register containing the holder. 513014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return return_holder ? reg : no_reg; 514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { 518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!miss->is_unused()) { 519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label success; 520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&success); 521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(miss); 522f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (IC::ShouldPushPopSlotAndVector(kind())) { 523958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(kind() == Code::LOAD_IC); 524958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PopVectorAndSlot(); 525958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TailCallBuiltin(masm(), MissBuiltin(kind())); 527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&success); 528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { 533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!miss->is_unused()) { 534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label success; 535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&success); 536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateRestoreName(miss, name); 537f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DCHECK(!IC::ShouldPushPopSlotAndVector(kind())); 538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TailCallBuiltin(masm(), MissBuiltin(kind())); 539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&success); 540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { 545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the constant value. 546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadObject(eax, value); 547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup( 552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LookupIterator* it, Register holder_reg) { 553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(holder()->HasNamedInterceptor()); 55413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate())); 555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compile the interceptor call, followed by inline code to load the 557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // property from further up the prototype chain if the call fails. 558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the maps haven't changed. 559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1())); 560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Preserve the receiver register explicitly whenever it is different from the 562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // holder and it is needed should the interceptor return without any result. 563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The ACCESSOR case needs the receiver to be passed into C++ code, the FIELD 564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // case might cause a miss during the prototype check. 565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool must_perform_prototype_check = 566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !holder().is_identical_to(it->GetHolder<JSObject>()); 567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool must_preserve_receiver_reg = 568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !receiver().is(holder_reg) && 569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (it->state() == LookupIterator::ACCESSOR || must_perform_prototype_check); 570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save necessary data before invoking an interceptor. 572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Requires a frame to make GC aware of pushed pointers. 573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope frame_scope(masm(), StackFrame::INTERNAL); 575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (must_preserve_receiver_reg) { 577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(receiver()); 578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(holder_reg); 580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(this->name()); 581958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier InterceptorVectorSlotPush(holder_reg); 582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Invoke an interceptor. Note: map checks from receiver to 583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // interceptor's holder has been compiled before (see a caller 584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of this method.) 585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CompileCallLoadPropertyWithInterceptor( 586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm(), receiver(), holder_reg, this->name(), holder(), 587014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Runtime::kLoadPropertyWithInterceptorOnly); 588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if interceptor provided a value for property. If it's 590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the case, return immediately. 591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label interceptor_failed; 592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(eax, factory()->no_interceptor_result_sentinel()); 593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &interceptor_failed); 594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch frame_scope.GenerateLeaveFrame(); 595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Clobber registers when generating debug-code to provoke errors. 598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&interceptor_failed); 599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code) { 600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(receiver(), Immediate(bit_cast<int32_t>(kZapValue))); 601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(holder_reg, Immediate(bit_cast<int32_t>(kZapValue))); 602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(this->name(), Immediate(bit_cast<int32_t>(kZapValue))); 603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 605958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier InterceptorVectorSlotPop(holder_reg); 606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(this->name()); 607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(holder_reg); 608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (must_preserve_receiver_reg) { 609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(receiver()); 610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Leave the internal frame. 613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateLoadPostInterceptor(it, holder_reg); 616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) { 620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(holder()->HasNamedInterceptor()); 62113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate())); 622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the runtime system to load the interceptor. 623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(scratch2()); // save old return address 624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(), 625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch holder()); 626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(scratch2()); // restore old return address 627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 628014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kLoadPropertyWithInterceptor); 629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 631f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid NamedStoreHandlerCompiler::ZapStackArgumentsRegisterAliases() { 632f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Zap register aliases of the arguments passed on the stack to ensure they 633f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // are properly loaded by the handler (debug-only). 634f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(Descriptor::kPassLastArgsOnStack); 635f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(Descriptor::kStackArgumentsCount == 3); 636f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(Descriptor::ValueRegister(), Immediate(kDebugZapValue)); 637f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(Descriptor::SlotRegister(), Immediate(kDebugZapValue)); 638f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(Descriptor::VectorRegister(), Immediate(kDebugZapValue)); 639f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( 642109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> callback, 643109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch LanguageMode language_mode) { 644958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register holder_reg = Frontend(name); 645f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ LoadParameterFromStack<Descriptor>(value(), Descriptor::kValue); 646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(scratch1()); // remove the return address 648f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Discard stack arguments. 649f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ add(esp, Immediate(StoreWithVectorDescriptor::kStackArgumentsCount * 650f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch kPointerSize)); 651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(receiver()); 652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(holder_reg); 653014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the callback cannot leak, then push the callback directly, 654014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // otherwise wrap it in a weak cell. 65513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (callback->data()->IsUndefined(isolate()) || callback->data()->IsSmi()) { 656014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(callback); 657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 658014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<WeakCell> cell = isolate()->factory()->NewWeakCell(callback); 659014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(cell); 660014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(name); 662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(value()); 663109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ push(Immediate(Smi::FromInt(language_mode))); 664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(scratch1()); // restore return address 665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do tail-call to the runtime system. 667014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kStoreCallbackProperty); 668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the generated code. 670bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return GetCode(kind(), name); 671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister NamedStoreHandlerCompiler::value() { 675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return StoreDescriptor::ValueRegister(); 676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( 680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { 681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label miss; 682f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (IC::ShouldPushPopSlotAndVector(kind())) { 683958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PushVectorAndSlot(); 684958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 685014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrontendHeader(receiver(), name, &miss, DONT_RETURN_ANYTHING); 686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the value from the cell. 687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = StoreDescriptor::ValueRegister(); 688958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell); 689958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ LoadWeakValue(result, weak_cell, &miss); 690958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ mov(result, FieldOperand(result, PropertyCell::kValueOffset)); 691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for deleted property if property can actually be deleted. 693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (is_configurable) { 694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(result, factory()->the_hole_value()); 695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &miss); 696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (FLAG_debug_code) { 697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(result, factory()->the_hole_value()); 698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); 699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Counters* counters = isolate()->counters(); 702109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ IncrementCounter(counters->ic_named_load_global_stub(), 1); 703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The code above already loads the result into the return register. 704f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (IC::ShouldPushPopSlotAndVector(kind())) { 705958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DiscardVectorAndSlot(); 706958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrontendFooter(name, &miss); 710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the generated code. 712bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return GetCode(kind(), name); 713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __ 717014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // V8_TARGET_ARCH_IA32 721