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_IA32 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 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadViaGetter( 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Handle<HeapType> type, Register receiver, 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSFunction> getter) { 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!getter.is_null()) { 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the JavaScript getter with the receiver on the stack. 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Swap in the global receiver. 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(receiver, 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(receiver); 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ParameterCount actual(0); 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ParameterCount expected(getter); 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeFunction(getter, expected, actual, CALL_FUNCTION, 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NullCallWrapper()); 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we generate a global code snippet for deoptimization only, remember 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the place to continue after deoptimization. 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore context register. 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Label* miss_label, Register receiver, 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name, Register scratch0, Register scratch1) { 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(name->IsUniqueName()); 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!receiver.is(scratch0)); 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Counters* counters = masm->isolate()->counters(); 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IncrementCounter(counters->negative_lookups(), 1); 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IncrementCounter(counters->negative_lookups_miss(), 1); 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch0, FieldOperand(receiver, HeapObject::kMapOffset)); 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kInterceptorOrAccessCheckNeededMask = 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Bail out if the receiver has a named interceptor or requires access checks. 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test_b(FieldOperand(scratch0, Map::kBitFieldOffset), 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kInterceptorOrAccessCheckNeededMask); 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, miss_label); 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that receiver is a JSObject. 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpInstanceType(scratch0, FIRST_SPEC_OBJECT_TYPE); 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(below, miss_label); 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load properties array. 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register properties = scratch0; 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the properties array is a dictionary. 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(FieldOperand(properties, HeapObject::kMapOffset), 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(masm->isolate()->factory()->hash_table_map())); 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, miss_label); 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionaryLookupStub::GenerateNegativeLookup(masm, miss_label, &done, 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch properties, name, scratch1); 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ DecrementCounter(counters->negative_lookups_miss(), 1); 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype( 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, int index, Register prototype, Label* miss) { 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the global function with the given index. 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSFunction> function( 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSFunction::cast(masm->isolate()->native_context()->get(index))); 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check we're still in the same context. 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch = prototype; 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch, Operand(esi, offset)); 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch, FieldOperand(scratch, GlobalObject::kNativeContextOffset)); 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(Operand(scratch, Context::SlotOffset(index)), function); 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, miss); 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load its initial map. The global functions all have initial maps. 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(prototype, Immediate(Handle<Map>(function->initial_map()))); 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the prototype from the initial map. 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype( 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Register receiver, Register scratch1, 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2, Label* miss_label) { 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(eax, scratch1); 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Generate call to api function. 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// This function uses push() to generate smaller, faster code than 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// the version above. It is an optimization that should will be removed 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// when api call ICs are generated in hydrogen. 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PropertyHandlerCompiler::GenerateFastApiCall( 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, const CallOptimization& optimization, 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> receiver_map, Register receiver, Register scratch_in, 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_store, int argc, Register* values) { 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Copy return value. 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(scratch_in); 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // receiver 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(receiver); 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Write the arguments to stack frame. 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < argc; i++) { 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register arg = values[argc - 1 - i]; 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!receiver.is(arg)); 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch_in.is(arg)); 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(arg); 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(scratch_in); 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Stack now matches JSFunction abi. 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(optimization.is_simple_api_call()); 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Abi for CallApiFunctionStub. 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register callee = eax; 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register call_data = ebx; 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register holder = ecx; 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register api_function_address = edx; 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch = edi; // scratch_in is no longer valid. 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Put holder in place. 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallOptimization::HolderLookup holder_lookup; 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> api_holder = 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch optimization.LookupHolderOfExpectedType(receiver_map, &holder_lookup); 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (holder_lookup) { 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CallOptimization::kHolderIsReceiver: 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(holder, receiver); 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CallOptimization::kHolderFound: 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadHeapObject(holder, api_holder); 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CallOptimization::kHolderNotFound: 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate = masm->isolate(); 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSFunction> function = optimization.constant_function(); 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> call_data_obj(api_call_info->data(), isolate); 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Put callee in place. 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadHeapObject(callee, function); 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool call_data_undefined = false; 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Put call_data in place. 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (isolate->heap()->InNewSpace(*call_data_obj)) { 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch, api_call_info); 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(call_data, FieldOperand(scratch, CallHandlerInfo::kDataOffset)); 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (call_data_obj->IsUndefined()) { 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch call_data_undefined = true; 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(call_data, Immediate(isolate->factory()->undefined_value())); 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(call_data, call_data_obj); 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Put api_function_address in place. 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address function_address = v8::ToCData<Address>(api_call_info->callback()); 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(api_function_address, Immediate(function_address)); 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Jump to stub. 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc); 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallStub(&stub); 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Generate code to check that a global property cell is empty. Create 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// the property cell at compilation time if no cell exists for the 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// property. 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PropertyHandlerCompiler::GenerateCheckPropertyCell( 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, Label* miss) { 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<PropertyCell> cell = JSGlobalObject::EnsurePropertyCell(global, name); 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(cell->value()->IsTheHole()); 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Oddball> the_hole = masm->isolate()->factory()->the_hole_value(); 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (masm->serializer_enabled()) { 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch, Immediate(cell)); 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(the_hole)); 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(Operand::ForCell(cell), Immediate(the_hole)); 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, miss); 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedStoreHandlerCompiler::GenerateStoreViaSetter( 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Handle<HeapType> type, Register receiver, 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSFunction> setter) { 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------- S t a t e ------------- 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- esp[0] : return address 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------------------------------- 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save value register, so we can restore it later. 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(value()); 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!setter.is_null()) { 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the JavaScript setter with receiver and value on the stack. 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Swap in the global receiver. 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(receiver, 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(receiver); 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(value()); 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ParameterCount actual(1); 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ParameterCount expected(setter); 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeFunction(setter, expected, actual, CALL_FUNCTION, 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NullCallWrapper()); 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we generate a global code snippet for deoptimization only, remember 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the place to continue after deoptimization. 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset()); 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We have to return the passed value, not the return value of the setter. 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(eax); 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore context register. 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void PushInterceptorArguments(MacroAssembler* masm, Register receiver, 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register holder, Register name, 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> holder_obj) { 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1); 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2); 262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3); 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 4); 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(name); 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!masm->isolate()->heap()->InNewSpace(*interceptor)); 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch = name; 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch, Immediate(interceptor)); 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(scratch); 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(receiver); 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(holder); 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CompileCallLoadPropertyWithInterceptor( 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Register receiver, Register holder, Register name, 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> holder_obj, IC::UtilityId id) { 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PushInterceptorArguments(masm, receiver, holder, name, holder_obj); 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallExternalReference(ExternalReference(IC_Utility(id), masm->isolate()), 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NamedLoadHandlerCompiler::kInterceptorArgsLength); 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void StoreIC_PushArgs(MacroAssembler* masm) { 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register receiver = StoreDescriptor::ReceiverRegister(); 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register name = StoreDescriptor::NameRegister(); 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value = StoreDescriptor::ValueRegister(); 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!ebx.is(receiver) && !ebx.is(name) && !ebx.is(value)); 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(ebx); 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(receiver); 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(name); 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(value); 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(ebx); 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedStoreHandlerCompiler::GenerateSlow(MacroAssembler* masm) { 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return address is on the stack. 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StoreIC_PushArgs(masm); 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do tail-call to runtime routine. 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference ref(IC_Utility(IC::kStoreIC_Slow), masm->isolate()); 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallExternalReference(ref, 3, 1); 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) { 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return address is on the stack. 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StoreIC_PushArgs(masm); 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do tail-call to runtime routine. 314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference ref(IC_Utility(IC::kKeyedStoreIC_Slow), masm->isolate()); 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallExternalReference(ref, 3, 1); 316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __ 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ ACCESS_MASM(masm()) 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name) { 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!label->is_unused()) { 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(label); 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(this->name(), Immediate(name)); 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Receiver_reg is preserved on jumps to miss_label, but may be destroyed if 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// store is successful. 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedStoreHandlerCompiler::GenerateStoreTransition( 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> transition, Handle<Name> name, Register receiver_reg, 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register storage_reg, Register value_reg, Register scratch1, 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2, Register unused, Label* miss_label, Label* slow) { 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int descriptor = transition->LastAdded(); 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DescriptorArray* descriptors = transition->instance_descriptors(); 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PropertyDetails details = descriptors->GetDetails(descriptor); 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Representation representation = details.representation(); 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!representation.IsNone()); 343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (details.type() == CONSTANT) { 345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> constant(descriptors->GetValue(descriptor), isolate()); 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObject(value_reg, constant); 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, miss_label); 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (representation.IsSmi()) { 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotSmi(value_reg, miss_label); 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (representation.IsHeapObject()) { 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(value_reg, miss_label); 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapType* field_type = descriptors->GetFieldType(descriptor); 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapType::Iterator<Map> it = field_type->Classes(); 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!it.Done()) { 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label do_store; 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (true) { 357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareMap(value_reg, it.Current()); 358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch it.Advance(); 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (it.Done()) { 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, miss_label); 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &do_store, Label::kNear); 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&do_store); 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (representation.IsDouble()) { 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label do_store, heap_number; 369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AllocateHeapNumber(storage_reg, scratch1, scratch2, slow, MUTABLE); 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotSmi(value_reg, &heap_number); 372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(value_reg); 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cvtsi2sd(xmm0, value_reg); 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(value_reg); 375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&do_store); 376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&heap_number); 378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CheckMap(value_reg, isolate()->factory()->heap_number_map(), miss_label, 379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DONT_DO_SMI_CHECK); 380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); 381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&do_store); 383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0); 384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Stub never generated for objects that require access checks. 387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!transition->is_access_check_needed()); 388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform map transition for the receiver if necessary. 390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (details.type() == FIELD && 391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { 392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The properties must be extended before we can store the value. 393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We jump to a runtime call that extends the properties array. 394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(scratch1); // Return address. 395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(receiver_reg); 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(transition)); 397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(value_reg); 398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(scratch1); 399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallExternalReference( 400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), 401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate()), 402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3, 1); 403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update the map of the object. 407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch1, Immediate(transition)); 408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset), scratch1); 409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update the write barrier for the map field. 411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteField(receiver_reg, HeapObject::kMapOffset, scratch1, scratch2, 412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kDontSaveFPRegs, OMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (details.type() == CONSTANT) { 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(value_reg.is(eax)); 416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int index = transition->instance_descriptors()->GetFieldIndex( 421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch transition->LastAdded()); 422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Adjust for the number of properties stored in the object. Even in the 424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // face of a transition we can use the old map here because the size of the 425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // object and the number of in-object properties is not going to change. 426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch index -= transition->inobject_properties(); 427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SmiCheck smi_check = 429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch representation.IsTagged() ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; 430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(verwaest): Share this code as a code stub. 431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (index < 0) { 432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Set the property straight into the object. 433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = transition->instance_size() + (index * kPointerSize); 434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (representation.IsDouble()) { 435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(FieldOperand(receiver_reg, offset), storage_reg); 436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(FieldOperand(receiver_reg, offset), value_reg); 438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!representation.IsSmi()) { 441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update the write barrier for the array address. 442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!representation.IsDouble()) { 443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(storage_reg, value_reg); 444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteField(receiver_reg, offset, storage_reg, scratch1, 446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kDontSaveFPRegs, EMIT_REMEMBERED_SET, smi_check); 447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Write to the properties array. 450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = index * kPointerSize + FixedArray::kHeaderSize; 451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the properties array (optimistically). 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); 453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (representation.IsDouble()) { 454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(FieldOperand(scratch1, offset), storage_reg); 455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(FieldOperand(scratch1, offset), value_reg); 457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!representation.IsSmi()) { 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update the write barrier for the array address. 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!representation.IsDouble()) { 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(storage_reg, value_reg); 463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteField(scratch1, offset, storage_reg, receiver_reg, 465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kDontSaveFPRegs, EMIT_REMEMBERED_SET, smi_check); 466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the value (register eax). 470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(value_reg.is(eax)); 471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedStoreHandlerCompiler::GenerateStoreField(LookupIterator* lookup, 476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value_reg, 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* miss_label) { 478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(lookup->representation().IsHeapObject()); 479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(value_reg, miss_label); 480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapType::Iterator<Map> it = lookup->GetFieldType()->Classes(); 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label do_store; 482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (true) { 483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareMap(value_reg, it.Current()); 484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch it.Advance(); 485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (it.Done()) { 486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, miss_label); 487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &do_store, Label::kNear); 490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&do_store); 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StoreFieldStub stub(isolate(), lookup->GetFieldIndex(), 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch lookup->representation()); 495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateTailCall(masm(), stub.GetCode()); 496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister PropertyHandlerCompiler::CheckPrototypes( 500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object_reg, Register holder_reg, Register scratch1, 501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2, Handle<Name> name, Label* miss, 502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrototypeCheckType check) { 503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); 504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Make sure there's no overlap between holder and object registers. 506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && 508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !scratch2.is(scratch1)); 509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Keep track of the current object in register reg. 511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg = object_reg; 512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int depth = 0; 513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> current = Handle<JSObject>::null(); 515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (type()->IsConstant()) 516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch current = Handle<JSObject>::cast(type()->AsConstant()->Value()); 517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> prototype = Handle<JSObject>::null(); 518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> current_map = receiver_map; 519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> holder_map(holder()->map()); 520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Traverse the prototype chain and check the maps in the prototype chain for 521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // fast and global objects or do negative lookup for normal objects. 522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (!current_map.is_identical_to(holder_map)) { 523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++depth; 524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Only global objects and objects that do not require access 526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // checks are allowed in stubs. 527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(current_map->IsJSGlobalProxyMap() || 528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !current_map->is_access_check_needed()); 529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch prototype = handle(JSObject::cast(current_map->prototype())); 531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (current_map->is_dictionary_map() && 532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !current_map->IsJSGlobalObjectMap()) { 533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. 534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!name->IsUniqueName()) { 535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(name->IsString()); 536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name = factory()->InternalizeString(Handle<String>::cast(name)); 537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(current.is_null() || 539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch current->property_dictionary()->FindEntry(name) == 540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionary::kNotFound); 541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, 543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scratch2); 544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); 546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg = holder_reg; // From now on the object will be in holder_reg. 547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); 548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool in_new_space = heap()->InNewSpace(*prototype); 550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Two possible reasons for loading the prototype from the map: 551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (1) Can't store references to new space in code. 552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (2) Handler is shared for all receivers with the same prototype 553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // map (but not necessarily the same prototype instance). 554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool load_prototype_from_map = in_new_space || depth == 1; 555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (depth != 1 || check == CHECK_ALL_MAPS) { 556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK); 557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check access rights to the global object. This has to happen after 560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the map check so that we know that the object is actually a global 561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // object. 562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This allows us to install generated handlers for accesses to the 563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // global proxy (as opposed to using slow ICs). See corresponding code 564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // in LookupForRead(). 565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (current_map->IsJSGlobalProxyMap()) { 566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); 567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (current_map->IsJSGlobalObjectMap()) { 568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), 569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name, scratch2, miss); 570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (load_prototype_from_map) { 573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save the map in scratch1 for later. 574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); 575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg = holder_reg; // From now on the object will be in holder_reg. 578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (load_prototype_from_map) { 580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); 581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(reg, prototype); 583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Go to the next object in the prototype chain. 587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch current = prototype; 588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch current_map = handle(current->map()); 589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Log the check depth. 592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); 593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (depth != 0 || check == CHECK_ALL_MAPS) { 595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check the holder map. 596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK); 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform security check for access to the global object. 600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(current_map->IsJSGlobalProxyMap() || 601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !current_map->is_access_check_needed()); 602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (current_map->IsJSGlobalProxyMap()) { 603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); 604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the register containing the holder. 607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return reg; 608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { 612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!miss->is_unused()) { 613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label success; 614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&success); 615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(miss); 616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TailCallBuiltin(masm(), MissBuiltin(kind())); 617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&success); 618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { 623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!miss->is_unused()) { 624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label success; 625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&success); 626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateRestoreName(miss, name); 627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TailCallBuiltin(masm(), MissBuiltin(kind())); 628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&success); 629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadCallback( 634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg, Handle<ExecutableAccessorInfo> callback) { 635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Insert additional parameters into the stack frame above return address. 636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch3().is(reg)); 637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(scratch3()); // Get return address to place it below. 638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); 640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); 641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); 642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); 643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); 644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); 645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(receiver()); // receiver 646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push data from ExecutableAccessorInfo. 647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (isolate()->heap()->InNewSpace(callback->data())) { 648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch2().is(reg)); 649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch2(), Immediate(callback)); 650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(FieldOperand(scratch2(), ExecutableAccessorInfo::kDataOffset)); 651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(Handle<Object>(callback->data(), isolate()))); 653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(isolate()->factory()->undefined_value())); // ReturnValue 655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ReturnValue default value 656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(isolate()->factory()->undefined_value())); 657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(reinterpret_cast<int>(isolate()))); 658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(reg); // holder 659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save a pointer to where we pushed the arguments. This will be 661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // passed as the const PropertyAccessorInfo& to the C++ callback. 662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(esp); 663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(name()); // name 665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(scratch3()); // Restore return address. 667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Abi for CallApiGetter 669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register getter_address = ApiGetterDescriptor::function_address(); 670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address function_address = v8::ToCData<Address>(callback->getter()); 671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(getter_address, Immediate(function_address)); 672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallApiGetterStub stub(isolate()); 674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallStub(&stub); 675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { 679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the constant value. 680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadObject(eax, value); 681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup( 686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LookupIterator* it, Register holder_reg) { 687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(holder()->HasNamedInterceptor()); 688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); 689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compile the interceptor call, followed by inline code to load the 691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // property from further up the prototype chain if the call fails. 692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the maps haven't changed. 693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1())); 694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Preserve the receiver register explicitly whenever it is different from the 696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // holder and it is needed should the interceptor return without any result. 697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The ACCESSOR case needs the receiver to be passed into C++ code, the FIELD 698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // case might cause a miss during the prototype check. 699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool must_perform_prototype_check = 700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !holder().is_identical_to(it->GetHolder<JSObject>()); 701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool must_preserve_receiver_reg = 702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !receiver().is(holder_reg) && 703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (it->state() == LookupIterator::ACCESSOR || must_perform_prototype_check); 704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save necessary data before invoking an interceptor. 706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Requires a frame to make GC aware of pushed pointers. 707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope frame_scope(masm(), StackFrame::INTERNAL); 709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (must_preserve_receiver_reg) { 711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(receiver()); 712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(holder_reg); 714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(this->name()); 715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Invoke an interceptor. Note: map checks from receiver to 717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // interceptor's holder has been compiled before (see a caller 718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of this method.) 719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CompileCallLoadPropertyWithInterceptor( 720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm(), receiver(), holder_reg, this->name(), holder(), 721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IC::kLoadPropertyWithInterceptorOnly); 722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if interceptor provided a value for property. If it's 724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the case, return immediately. 725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label interceptor_failed; 726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(eax, factory()->no_interceptor_result_sentinel()); 727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &interceptor_failed); 728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch frame_scope.GenerateLeaveFrame(); 729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Clobber registers when generating debug-code to provoke errors. 732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&interceptor_failed); 733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code) { 734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(receiver(), Immediate(bit_cast<int32_t>(kZapValue))); 735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(holder_reg, Immediate(bit_cast<int32_t>(kZapValue))); 736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(this->name(), Immediate(bit_cast<int32_t>(kZapValue))); 737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(this->name()); 740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(holder_reg); 741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (must_preserve_receiver_reg) { 742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(receiver()); 743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Leave the internal frame. 746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateLoadPostInterceptor(it, holder_reg); 749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) { 753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(holder()->HasNamedInterceptor()); 754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); 755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the runtime system to load the interceptor. 756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(scratch2()); // save old return address 757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(), 758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch holder()); 759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(scratch2()); // restore old return address 760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference ref = ExternalReference( 762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IC_Utility(IC::kLoadPropertyWithInterceptor), isolate()); 763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallExternalReference( 764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); 765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( 769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> object, Handle<Name> name, 770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<ExecutableAccessorInfo> callback) { 771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register holder_reg = Frontend(receiver(), name); 772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(scratch1()); // remove the return address 774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(receiver()); 775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(holder_reg); 776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(callback); 777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(name); 778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(value()); 779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(scratch1()); // restore return address 780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do tail-call to the runtime system. 782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference store_callback_property = 783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); 784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallExternalReference(store_callback_property, 5, 1); 785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the generated code. 787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return GetCode(kind(), Code::FAST, name); 788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( 792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name) { 793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(scratch1()); // remove the return address 794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(receiver()); 795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(this->name()); 796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(value()); 797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(scratch1()); // restore return address 798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do tail-call to the runtime system. 800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference store_ic_property = ExternalReference( 801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); 802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallExternalReference(store_ic_property, 3, 1); 803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the generated code. 805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return GetCode(kind(), Code::FAST, name); 806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister NamedStoreHandlerCompiler::value() { 810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return StoreDescriptor::ValueRegister(); 811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( 815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { 816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label miss; 817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrontendHeader(receiver(), name, &miss); 819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the value from the cell. 820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = StoreDescriptor::ValueRegister(); 821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (masm()->serializer_enabled()) { 822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, Immediate(cell)); 823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, FieldOperand(result, PropertyCell::kValueOffset)); 824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, Operand::ForCell(cell)); 826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for deleted property if property can actually be deleted. 829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (is_configurable) { 830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(result, factory()->the_hole_value()); 831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &miss); 832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (FLAG_debug_code) { 833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(result, factory()->the_hole_value()); 834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); 835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Counters* counters = isolate()->counters(); 838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IncrementCounter(counters->named_load_global_stub(), 1); 839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The code above already loads the result into the return register. 840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrontendFooter(name, &miss); 843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the generated code. 845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return GetCode(kind(), Code::NORMAL, name); 846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __ 850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace v8::internal 852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // V8_TARGET_ARCH_IA32 854