handler-compiler-ppc.cc revision 958fae7ec3f466955f8e5b50fa5b8d38b9e91675
1958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Copyright 2014 the V8 project authors. All rights reserved.
2958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Use of this source code is governed by a BSD-style license that can be
3958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// found in the LICENSE file.
4958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
5958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/v8.h"
6958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
7958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#if V8_TARGET_ARCH_PPC
8958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
9958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/ic/call-optimization.h"
10958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/ic/handler-compiler.h"
11958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/ic/ic.h"
12958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
13958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace v8 {
14958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace internal {
15958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
16958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#define __ ACCESS_MASM(masm)
17958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
18958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
19958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::GenerateLoadViaGetter(
20958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    MacroAssembler* masm, Handle<HeapType> type, Register receiver,
21958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Handle<JSFunction> getter) {
22958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // ----------- S t a t e -------------
23958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  -- r3    : receiver
24958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  -- r5    : name
25958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  -- lr    : return address
26958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // -----------------------------------
27958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  {
28958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
29958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
30958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (!getter.is_null()) {
31958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // Call the JavaScript getter with the receiver on the stack.
32958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
33958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // Swap in the global receiver.
34958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ LoadP(receiver,
35958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                 FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
36958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
37958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ push(receiver);
38958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      ParameterCount actual(0);
39958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      ParameterCount expected(getter);
40958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ InvokeFunction(getter, expected, actual, CALL_FUNCTION,
41958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                        NullCallWrapper());
42958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
43958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // If we generate a global code snippet for deoptimization only, remember
44958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // the place to continue after deoptimization.
45958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset());
46958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
47958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
48958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Restore context register.
49958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
50958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
51958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
52958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
53958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
54958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
55958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::GenerateStoreViaSetter(
56958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    MacroAssembler* masm, Handle<HeapType> type, Register receiver,
57958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Handle<JSFunction> setter) {
58958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // ----------- S t a t e -------------
59958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  -- lr    : return address
60958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // -----------------------------------
61958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  {
62958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
63958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
64958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Save value register, so we can restore it later.
65958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ push(value());
66958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
67958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (!setter.is_null()) {
68958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // Call the JavaScript setter with receiver and value on the stack.
69958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
70958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // Swap in the global receiver.
71958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ LoadP(receiver,
72958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                 FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
73958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
74958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ Push(receiver, value());
75958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      ParameterCount actual(1);
76958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      ParameterCount expected(setter);
77958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ InvokeFunction(setter, expected, actual, CALL_FUNCTION,
78958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                        NullCallWrapper());
79958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
80958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // If we generate a global code snippet for deoptimization only, remember
81958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // the place to continue after deoptimization.
82958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset());
83958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
84958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
85958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // We have to return the passed value, not the return value of the setter.
86958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ pop(r3);
87958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
88958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Restore context register.
89958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
90958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
91958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
92958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
93958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
94958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
95958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
96958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    MacroAssembler* masm, Label* miss_label, Register receiver,
97958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Handle<Name> name, Register scratch0, Register scratch1) {
98958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(name->IsUniqueName());
99958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!receiver.is(scratch0));
100958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Counters* counters = masm->isolate()->counters();
101958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1);
102958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
104958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label done;
105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  const int kInterceptorOrAccessCheckNeededMask =
107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
108958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Bail out if the receiver has a named interceptor or requires access checks.
110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register map = scratch1;
111958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(map, FieldMemOperand(receiver, HeapObject::kMapOffset));
112958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ lbz(scratch0, FieldMemOperand(map, Map::kBitFieldOffset));
113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ andi(r0, scratch0, Operand(kInterceptorOrAccessCheckNeededMask));
114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(miss_label, cr0);
115958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
116958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check that receiver is a JSObject.
117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ lbz(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset));
118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmpi(scratch0, Operand(FIRST_SPEC_OBJECT_TYPE));
119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ blt(miss_label);
120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Load properties array.
122958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register properties = scratch0;
123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check that the properties array is a dictionary.
125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(map, FieldMemOperand(properties, HeapObject::kMapOffset));
126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register tmp = properties;
127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadRoot(tmp, Heap::kHashTableMapRootIndex);
128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmp(map, tmp);
129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(miss_label);
130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Restore the temporarily used register.
132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  NameDictionaryLookupStub::GenerateNegativeLookup(
136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      masm, miss_label, &done, receiver, properties, name, scratch1);
137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&done);
138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
139958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype(
143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    MacroAssembler* masm, int index, Register prototype, Label* miss) {
144958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Isolate* isolate = masm->isolate();
145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Get the global function with the given index.
146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<JSFunction> function(
147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      JSFunction::cast(isolate->native_context()->get(index)));
148958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check we're still in the same context.
150958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register scratch = prototype;
151958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX);
152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(scratch, MemOperand(cp, offset));
153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(scratch,
154958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier           FieldMemOperand(scratch, GlobalObject::kNativeContextOffset));
155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(scratch, MemOperand(scratch, Context::SlotOffset(index)));
156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Move(ip, function);
157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmp(ip, scratch);
158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(miss);
159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
160958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Load its initial map. The global functions all have initial maps.
161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Move(prototype, Handle<Map>(function->initial_map()));
162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Load the prototype from the initial map.
163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset));
164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
165958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
166958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
167958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(
168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    MacroAssembler* masm, Register receiver, Register scratch1,
169958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Register scratch2, Label* miss_label) {
170958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mr(r3, scratch1);
172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
173958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
174958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
175958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
176958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Generate code to check that a global property cell is empty. Create
177958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// the property cell at compilation time if no cell exists for the
178958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// property.
179958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid PropertyHandlerCompiler::GenerateCheckPropertyCell(
180958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name,
181958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Register scratch, Label* miss) {
182958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<Cell> cell = JSGlobalObject::EnsurePropertyCell(global, name);
183958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(cell->value()->IsTheHole());
184958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(scratch, Operand(cell));
185958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(scratch, FieldMemOperand(scratch, Cell::kValueOffset));
186958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
187958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmp(scratch, ip);
188958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(miss);
189958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
190958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
191958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
192958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void PushInterceptorArguments(MacroAssembler* masm, Register receiver,
193958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     Register holder, Register name,
194958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     Handle<JSObject> holder_obj) {
195958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0);
196958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1);
197958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2);
198958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3);
199958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 4);
200958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ push(name);
201958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor());
202958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!masm->isolate()->heap()->InNewSpace(*interceptor));
203958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register scratch = name;
204958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(scratch, Operand(interceptor));
205958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ push(scratch);
206958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ push(receiver);
207958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ push(holder);
208958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
210958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
211958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void CompileCallLoadPropertyWithInterceptor(
212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    MacroAssembler* masm, Register receiver, Register holder, Register name,
213958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Handle<JSObject> holder_obj, IC::UtilityId id) {
214958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
215958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ CallExternalReference(ExternalReference(IC_Utility(id), masm->isolate()),
216958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                           NamedLoadHandlerCompiler::kInterceptorArgsLength);
217958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
218958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
219958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
220958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Generate call to api function.
221958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid PropertyHandlerCompiler::GenerateFastApiCall(
222958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    MacroAssembler* masm, const CallOptimization& optimization,
223958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Handle<Map> receiver_map, Register receiver, Register scratch_in,
224958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    bool is_store, int argc, Register* values) {
225958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!receiver.is(scratch_in));
226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ push(receiver);
227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Write the arguments to stack frame.
228958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  for (int i = 0; i < argc; i++) {
229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Register arg = values[argc - 1 - i];
230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(!receiver.is(arg));
231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(!scratch_in.is(arg));
232958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ push(arg);
233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(optimization.is_simple_api_call());
235958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
236958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Abi for CallApiFunctionStub.
237958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register callee = r3;
238958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register call_data = r7;
239958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register holder = r5;
240958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register api_function_address = r4;
241958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
242958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Put holder in place.
243958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CallOptimization::HolderLookup holder_lookup;
244958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<JSObject> api_holder =
245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      optimization.LookupHolderOfExpectedType(receiver_map, &holder_lookup);
246958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  switch (holder_lookup) {
247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    case CallOptimization::kHolderIsReceiver:
248958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ Move(holder, receiver);
249958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      break;
250958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    case CallOptimization::kHolderFound:
251958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ Move(holder, api_holder);
252958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      break;
253958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    case CallOptimization::kHolderNotFound:
254958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      UNREACHABLE();
255958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      break;
256958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
257958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
258958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Isolate* isolate = masm->isolate();
259958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<JSFunction> function = optimization.constant_function();
260958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
261958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<Object> call_data_obj(api_call_info->data(), isolate);
262958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
263958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Put callee in place.
264958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Move(callee, function);
265958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
266958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool call_data_undefined = false;
267958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Put call_data in place.
268958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (isolate->heap()->InNewSpace(*call_data_obj)) {
269958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ Move(call_data, api_call_info);
270958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ LoadP(call_data,
271958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             FieldMemOperand(call_data, CallHandlerInfo::kDataOffset));
272958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else if (call_data_obj->IsUndefined()) {
273958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    call_data_undefined = true;
274958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ LoadRoot(call_data, Heap::kUndefinedValueRootIndex);
275958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
276958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ Move(call_data, call_data_obj);
277958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
278958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
279958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Put api_function_address in place.
280958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Address function_address = v8::ToCData<Address>(api_call_info->callback());
281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ApiFunction fun(function_address);
282958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ExternalReference::Type type = ExternalReference::DIRECT_API_CALL;
283958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ExternalReference ref = ExternalReference(&fun, type, masm->isolate());
284958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(api_function_address, Operand(ref));
285958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
286958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Jump to stub.
287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc);
288958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ TailCallStub(&stub);
289958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
292958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::GenerateSlow(MacroAssembler* masm) {
293958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Push receiver, key and value for runtime call.
294958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(),
295958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          StoreDescriptor::ValueRegister());
296958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
297958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // The slow case calls into the runtime to complete the store without causing
298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // an IC miss that would otherwise cause a transition to the generic stub.
299958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ExternalReference ref =
300958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      ExternalReference(IC_Utility(IC::kStoreIC_Slow), masm->isolate());
301958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ TailCallExternalReference(ref, 3, 1);
302958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
303958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
304958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
305958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) {
306958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Push receiver, key and value for runtime call.
307958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(),
308958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          StoreDescriptor::ValueRegister());
309958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
310958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // The slow case calls into the runtime to complete the store without causing
311958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // an IC miss that would otherwise cause a transition to the generic stub.
312958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ExternalReference ref =
313958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      ExternalReference(IC_Utility(IC::kKeyedStoreIC_Slow), masm->isolate());
314958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ TailCallExternalReference(ref, 3, 1);
315958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
316958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
317958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
318958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#undef __
319958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#define __ ACCESS_MASM(masm())
320958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
321958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                    Handle<Name> name) {
324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (!label->is_unused()) {
325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ bind(label);
326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ mov(this->name(), Operand(name));
327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::GenerateRestoreNameAndMap(
332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Handle<Name> name, Handle<Map> transition) {
333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(this->name(), Operand(name));
334958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(StoreTransitionDescriptor::MapRegister(), Operand(transition));
335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::GenerateConstantCheck(Object* constant,
339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                      Register value_reg,
340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                      Label* miss_label) {
341958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Move(scratch1(), handle(constant, isolate()));
342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmp(value_reg, scratch1());
343958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(miss_label);
344958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
345958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
346958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
347958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::GenerateFieldTypeChecks(HeapType* field_type,
348958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                        Register value_reg,
349958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                        Label* miss_label) {
350958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ JumpIfSmi(value_reg, miss_label);
351958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  HeapType::Iterator<Map> it = field_type->Classes();
352958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (!it.Done()) {
353958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ LoadP(scratch1(), FieldMemOperand(value_reg, HeapObject::kMapOffset));
354958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Label do_store;
355958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    while (true) {
356958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ CompareMap(scratch1(), it.Current(), &do_store);
357958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      it.Advance();
358958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (it.Done()) {
359958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ bne(miss_label);
360958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
361958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
362958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ beq(&do_store);
363958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
364958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ bind(&do_store);
365958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
366958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
367958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
368958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
369958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRegister PropertyHandlerCompiler::CheckPrototypes(
370958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Register object_reg, Register holder_reg, Register scratch1,
371958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Register scratch2, Handle<Name> name, Label* miss,
372958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    PrototypeCheckType check) {
373958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate()));
374958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
375958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Make sure there's no overlap between holder and object registers.
376958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
377958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) &&
378958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier         !scratch2.is(scratch1));
379958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
380958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Keep track of the current object in register reg.
381958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register reg = object_reg;
382958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int depth = 0;
383958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
384958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<JSObject> current = Handle<JSObject>::null();
385958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (type()->IsConstant()) {
386958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    current = Handle<JSObject>::cast(type()->AsConstant()->Value());
387958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
388958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<JSObject> prototype = Handle<JSObject>::null();
389958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<Map> current_map = receiver_map;
390958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<Map> holder_map(holder()->map());
391958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Traverse the prototype chain and check the maps in the prototype chain for
392958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // fast and global objects or do negative lookup for normal objects.
393958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  while (!current_map.is_identical_to(holder_map)) {
394958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    ++depth;
395958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
396958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Only global objects and objects that do not require access
397958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // checks are allowed in stubs.
398958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(current_map->IsJSGlobalProxyMap() ||
399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier           !current_map->is_access_check_needed());
400958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
401958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    prototype = handle(JSObject::cast(current_map->prototype()));
402958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (current_map->is_dictionary_map() &&
403958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        !current_map->IsJSGlobalObjectMap()) {
404958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      DCHECK(!current_map->IsJSGlobalProxyMap());  // Proxy maps are fast.
405958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (!name->IsUniqueName()) {
406958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        DCHECK(name->IsString());
407958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        name = factory()->InternalizeString(Handle<String>::cast(name));
408958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
409958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      DCHECK(current.is_null() ||
410958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             current->property_dictionary()->FindEntry(name) ==
411958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                 NameDictionary::kNotFound);
412958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1,
414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                       scratch2);
415958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
416958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ LoadP(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
417958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      reg = holder_reg;  // From now on the object will be in holder_reg.
418958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ LoadP(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
419958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
420958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Register map_reg = scratch1;
421958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (depth != 1 || check == CHECK_ALL_MAPS) {
422958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // CheckMap implicitly loads the map of |reg| into |map_reg|.
423958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ CheckMap(reg, map_reg, current_map, miss, DONT_DO_SMI_CHECK);
424958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
425958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ LoadP(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));
426958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
427958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
428958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // Check access rights to the global object.  This has to happen after
429958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // the map check so that we know that the object is actually a global
430958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // object.
431958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // This allows us to install generated handlers for accesses to the
432958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // global proxy (as opposed to using slow ICs). See corresponding code
433958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // in LookupForRead().
434958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (current_map->IsJSGlobalProxyMap()) {
435958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ CheckAccessGlobalProxy(reg, scratch2, miss);
436958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else if (current_map->IsJSGlobalObjectMap()) {
437958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
438958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                  name, scratch2, miss);
439958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
440958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
441958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      reg = holder_reg;  // From now on the object will be in holder_reg.
442958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
443958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // Two possible reasons for loading the prototype from the map:
444958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // (1) Can't store references to new space in code.
445958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // (2) Handler is shared for all receivers with the same prototype
446958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      //     map (but not necessarily the same prototype instance).
447958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      bool load_prototype_from_map =
448958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          heap()->InNewSpace(*prototype) || depth == 1;
449958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (load_prototype_from_map) {
450958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ LoadP(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset));
451958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
452958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ mov(reg, Operand(prototype));
453958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
454958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
455958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
456958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Go to the next object in the prototype chain.
457958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    current = prototype;
458958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    current_map = handle(current->map());
459958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
460958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
461958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Log the check depth.
462958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
463958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
464958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (depth != 0 || check == CHECK_ALL_MAPS) {
465958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Check the holder map.
466958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK);
467958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
468958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
469958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Perform security check for access to the global object.
470958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(current_map->IsJSGlobalProxyMap() ||
471958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier         !current_map->is_access_check_needed());
472958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (current_map->IsJSGlobalProxyMap()) {
473958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ CheckAccessGlobalProxy(reg, scratch1, miss);
474958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
475958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
476958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Return the register containing the holder.
477958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return reg;
478958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
479958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
480958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
481958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
482958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (!miss->is_unused()) {
483958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Label success;
484958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ b(&success);
485958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ bind(miss);
486958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    TailCallBuiltin(masm(), MissBuiltin(kind()));
487958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ bind(&success);
488958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
489958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
490958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
491958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
492958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
493958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (!miss->is_unused()) {
494958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Label success;
495958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ b(&success);
496958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    GenerateRestoreName(miss, name);
497958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    TailCallBuiltin(masm(), MissBuiltin(kind()));
498958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ bind(&success);
499958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
500958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
501958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
502958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
503958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) {
504958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Return the constant value.
505958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Move(r3, value);
506958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
507958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
508958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
509958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
510958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::GenerateLoadCallback(
511958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Register reg, Handle<ExecutableAccessorInfo> callback) {
512958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Build AccessorInfo::args_ list on the stack and push property name below
513958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // the exit frame to make GC aware of them and store pointers to them.
514958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0);
515958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1);
516958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2);
517958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3);
518958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4);
519958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5);
520958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6);
521958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!scratch2().is(reg));
522958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!scratch3().is(reg));
523958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!scratch4().is(reg));
524958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ push(receiver());
525958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (heap()->InNewSpace(callback->data())) {
526958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ Move(scratch3(), callback);
527958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ LoadP(scratch3(),
528958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             FieldMemOperand(scratch3(), ExecutableAccessorInfo::kDataOffset));
529958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
530958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ Move(scratch3(), Handle<Object>(callback->data(), isolate()));
531958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
532958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ push(scratch3());
533958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadRoot(scratch3(), Heap::kUndefinedValueRootIndex);
534958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mr(scratch4(), scratch3());
535958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Push(scratch3(), scratch4());
536958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(scratch4(), Operand(ExternalReference::isolate_address(isolate())));
537958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Push(scratch4(), reg);
538958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ push(name());
539958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
540958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Abi for CallApiGetter
541958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register getter_address_reg = ApiGetterDescriptor::function_address();
542958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
543958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Address getter_address = v8::ToCData<Address>(callback->getter());
544958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ApiFunction fun(getter_address);
545958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
546958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ExternalReference ref = ExternalReference(&fun, type, isolate());
547958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(getter_address_reg, Operand(ref));
548958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
549958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CallApiGetterStub stub(isolate());
550958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ TailCallStub(&stub);
551958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
552958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
553958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
554958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
555958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    LookupIterator* it, Register holder_reg) {
556958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(holder()->HasNamedInterceptor());
557958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
558958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
559958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Compile the interceptor call, followed by inline code to load the
560958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // property from further up the prototype chain if the call fails.
561958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check that the maps haven't changed.
562958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1()));
563958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
564958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Preserve the receiver register explicitly whenever it is different from the
565958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // holder and it is needed should the interceptor return without any result.
566958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // The ACCESSOR case needs the receiver to be passed into C++ code, the FIELD
567958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // case might cause a miss during the prototype check.
568958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool must_perform_prototype_check =
569958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      !holder().is_identical_to(it->GetHolder<JSObject>());
570958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool must_preserve_receiver_reg =
571958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      !receiver().is(holder_reg) &&
572958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      (it->state() == LookupIterator::ACCESSOR || must_perform_prototype_check);
573958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
574958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Save necessary data before invoking an interceptor.
575958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Requires a frame to make GC aware of pushed pointers.
576958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  {
577958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    FrameAndConstantPoolScope frame_scope(masm(), StackFrame::INTERNAL);
578958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (must_preserve_receiver_reg) {
579958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ Push(receiver(), holder_reg, this->name());
580958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
581958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ Push(holder_reg, this->name());
582958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
583958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Invoke an interceptor.  Note: map checks from receiver to
584958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // interceptor's holder has been compiled before (see a caller
585958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // of this method.)
586958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    CompileCallLoadPropertyWithInterceptor(
587958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        masm(), receiver(), holder_reg, this->name(), holder(),
588958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        IC::kLoadPropertyWithInterceptorOnly);
589958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
590958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Check if interceptor provided a value for property.  If it's
591958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // the case, return immediately.
592958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Label interceptor_failed;
593958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex);
594958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ cmp(r3, scratch1());
595958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ beq(&interceptor_failed);
596958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    frame_scope.GenerateLeaveFrame();
597958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ Ret();
598958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
599958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ bind(&interceptor_failed);
600958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ pop(this->name());
601958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ pop(holder_reg);
602958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (must_preserve_receiver_reg) {
603958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ pop(receiver());
604958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
605958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Leave the internal frame.
606958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
607958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
608958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  GenerateLoadPostInterceptor(it, holder_reg);
609958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
610958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
611958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
612958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) {
613958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Call the runtime system to load the interceptor.
614958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(holder()->HasNamedInterceptor());
615958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
616958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(),
617958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                           holder());
618958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
619958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ExternalReference ref = ExternalReference(
620958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      IC_Utility(IC::kLoadPropertyWithInterceptor), isolate());
621958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ TailCallExternalReference(
622958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1);
623958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
624958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
625958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
626958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierHandle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
627958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Handle<JSObject> object, Handle<Name> name,
628958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Handle<ExecutableAccessorInfo> callback) {
629958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register holder_reg = Frontend(receiver(), name);
630958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
631958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Push(receiver(), holder_reg);  // receiver
632958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(ip, Operand(callback));    // callback info
633958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ push(ip);
634958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(ip, Operand(name));
635958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Push(ip, value());
636958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
637958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Do tail-call to the runtime system.
638958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ExternalReference store_callback_property =
639958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
640958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ TailCallExternalReference(store_callback_property, 5, 1);
641958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
642958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Return the generated code.
643958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return GetCode(kind(), Code::FAST, name);
644958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
645958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
646958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
647958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierHandle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor(
648958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Handle<Name> name) {
649958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Push(receiver(), this->name(), value());
650958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
651958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Do tail-call to the runtime system.
652958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ExternalReference store_ic_property = ExternalReference(
653958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      IC_Utility(IC::kStorePropertyWithInterceptor), isolate());
654958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ TailCallExternalReference(store_ic_property, 3, 1);
655958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
656958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Return the generated code.
657958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return GetCode(kind(), Code::FAST, name);
658958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
659958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
660958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
661958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRegister NamedStoreHandlerCompiler::value() {
662958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return StoreDescriptor::ValueRegister();
663958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
664958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
665958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
666958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierHandle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
667958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) {
668958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label miss;
669958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  FrontendHeader(receiver(), name, &miss);
670958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
671958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Get the value from the cell.
672958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register result = StoreDescriptor::ValueRegister();
673958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(result, Operand(cell));
674958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(result, FieldMemOperand(result, Cell::kValueOffset));
675958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
676958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check for deleted property if property can actually be deleted.
677958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (is_configurable) {
678958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
679958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ cmp(result, ip);
680958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ beq(&miss);
681958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
682958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
683958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Counters* counters = isolate()->counters();
684958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ IncrementCounter(counters->named_load_global_stub(), 1, r4, r6);
685958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
686958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
687958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  FrontendFooter(name, &miss);
688958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
689958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Return the generated code.
690958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return GetCode(kind(), Code::NORMAL, name);
691958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
692958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
693958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
694958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#undef __
695958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
696958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}  // namespace v8::internal
697958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
698958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif  // V8_TARGET_ARCH_ARM
699