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