1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2014 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_MIPS64
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/handler-compiler.h"
8342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch
91b268ca467c924004286c97bac133db489cf43d0Ben Murdoch#include "src/api-arguments.h"
10342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch#include "src/field-type.h"
11342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch#include "src/ic/call-optimization.h"
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/ic.h"
13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/isolate-inl.h"
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 {
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal {
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ ACCESS_MASM(masm)
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadViaGetter(
22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int accessor_index, int expected_arguments, Register scratch) {
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // ----------- S t a t e -------------
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- a0    : receiver
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- a2    : name
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- ra    : return address
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // -----------------------------------
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
321b268ca467c924004286c97bac133db489cf43d0Ben Murdoch    // Save context register
331b268ca467c924004286c97bac133db489cf43d0Ben Murdoch    __ push(cp);
341b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (accessor_index >= 0) {
36014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(!holder.is(scratch));
37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(!receiver.is(scratch));
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Call the JavaScript getter with the receiver on the stack.
39014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (map->IsJSGlobalObjectMap()) {
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Swap in the global receiver.
41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ ld(scratch,
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
43014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        receiver = scratch;
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ push(receiver);
46014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ LoadAccessor(a1, holder, accessor_index, ACCESSOR_GETTER);
471b268ca467c924004286c97bac133db489cf43d0Ben Murdoch      __ li(a0, Operand(V8_INT64_C(0)));
481b268ca467c924004286c97bac133db489cf43d0Ben Murdoch      __ Call(masm->isolate()->builtins()->CallFunction(
491b268ca467c924004286c97bac133db489cf43d0Ben Murdoch                  ConvertReceiverMode::kNotNullOrUndefined),
501b268ca467c924004286c97bac133db489cf43d0Ben Murdoch              RelocInfo::CODE_TARGET);
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // If we generate a global code snippet for deoptimization only, remember
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // the place to continue after deoptimization.
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset());
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Restore context register.
581b268ca467c924004286c97bac133db489cf43d0Ben Murdoch    __ pop(cp);
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Ret();
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedStoreHandlerCompiler::GenerateStoreViaSetter(
65014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
66014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int accessor_index, int expected_arguments, Register scratch) {
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // ----------- S t a t e -------------
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- ra    : return address
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // -----------------------------------
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
731b268ca467c924004286c97bac133db489cf43d0Ben Murdoch    // Save context and value registers, so we can restore them later.
741b268ca467c924004286c97bac133db489cf43d0Ben Murdoch    __ Push(cp, value());
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (accessor_index >= 0) {
77014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(!holder.is(scratch));
78014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(!receiver.is(scratch));
79014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(!value().is(scratch));
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Call the JavaScript setter with receiver and value on the stack.
81014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (map->IsJSGlobalObjectMap()) {
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Swap in the global receiver.
83014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ ld(scratch,
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        receiver = scratch;
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(receiver, value());
88014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ LoadAccessor(a1, holder, accessor_index, ACCESSOR_SETTER);
891b268ca467c924004286c97bac133db489cf43d0Ben Murdoch      __ li(a0, Operand(1));
901b268ca467c924004286c97bac133db489cf43d0Ben Murdoch      __ Call(masm->isolate()->builtins()->CallFunction(
911b268ca467c924004286c97bac133db489cf43d0Ben Murdoch                  ConvertReceiverMode::kNotNullOrUndefined),
921b268ca467c924004286c97bac133db489cf43d0Ben Murdoch              RelocInfo::CODE_TARGET);
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // If we generate a global code snippet for deoptimization only, remember
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // the place to continue after deoptimization.
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset());
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // We have to return the passed value, not the return value of the setter.
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Restore context register.
1011b268ca467c924004286c97bac133db489cf43d0Ben Murdoch    __ Pop(cp, v0);
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Ret();
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid PropertyHandlerCompiler::PushVectorAndSlot(Register vector,
108958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                Register slot) {
109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  MacroAssembler* masm = this->masm();
110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Push(vector, slot);
111958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
112958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid PropertyHandlerCompiler::PopVectorAndSlot(Register vector, Register slot) {
115958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  MacroAssembler* masm = this->masm();
116958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Pop(vector, slot);
117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid PropertyHandlerCompiler::DiscardVectorAndSlot() {
121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  MacroAssembler* masm = this->masm();
122958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Remove vector and slot.
123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Daddu(sp, sp, Operand(2 * kPointerSize));
124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MacroAssembler* masm, Label* miss_label, Register receiver,
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Name> name, Register scratch0, Register scratch1) {
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(name->IsUniqueName());
131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!receiver.is(scratch0));
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Counters* counters = masm->isolate()->counters();
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1);
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kInterceptorOrAccessCheckNeededMask =
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Bail out if the receiver has a named interceptor or requires access checks.
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register map = scratch1;
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ld(map, FieldMemOperand(receiver, HeapObject::kMapOffset));
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ lbu(scratch0, FieldMemOperand(map, Map::kBitFieldOffset));
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ And(scratch0, scratch0, Operand(kInterceptorOrAccessCheckNeededMask));
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Branch(miss_label, ne, scratch0, Operand(zero_reg));
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that receiver is a JSObject.
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ lbu(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset));
150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Branch(miss_label, lt, scratch0, Operand(FIRST_JS_RECEIVER_TYPE));
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load properties array.
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register properties = scratch0;
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ld(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that the properties array is a dictionary.
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ld(map, FieldMemOperand(properties, HeapObject::kMapOffset));
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register tmp = properties;
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(tmp, Heap::kHashTableMapRootIndex);
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Branch(miss_label, ne, map, Operand(tmp));
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Restore the temporarily used register.
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ld(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  NameDictionaryLookupStub::GenerateNegativeLookup(
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      masm, miss_label, &done, receiver, properties, name, scratch1);
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype(
173958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    MacroAssembler* masm, int index, Register result, Label* miss) {
174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadNativeContextSlot(index, result);
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load its initial map. The global functions all have initial maps.
176958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ ld(result,
177958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        FieldMemOperand(result, JSFunction::kPrototypeOrInitialMapOffset));
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the prototype from the initial map.
179958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ ld(result, FieldMemOperand(result, Map::kPrototypeOffset));
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MacroAssembler* masm, Register receiver, Register scratch1,
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch2, Label* miss_label) {
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Ret(USE_DELAY_SLOT);
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(v0, scratch1);
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Generate code to check that a global property cell is empty. Create
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// the property cell at compilation time if no cell exists for the
194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// property.
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PropertyHandlerCompiler::GenerateCheckPropertyCell(
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name,
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch, Label* miss) {
198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<PropertyCell> cell = JSGlobalObject::EnsurePropertyCell(global, name);
19921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  Isolate* isolate = masm->isolate();
20021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  DCHECK(cell->value()->IsTheHole(isolate));
20121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell);
202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadWeakValue(scratch, weak_cell, miss);
203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ ld(scratch, FieldMemOperand(scratch, PropertyCell::kValueOffset));
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Branch(miss, ne, scratch, Operand(at));
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void PushInterceptorArguments(MacroAssembler* masm, Register receiver,
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     Register holder, Register name,
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     Handle<JSObject> holder_obj) {
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0);
213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 1);
214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 2);
215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 3);
216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Push(name, receiver, holder);
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CompileCallLoadPropertyWithInterceptor(
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MacroAssembler* masm, Register receiver, Register holder, Register name,
222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Handle<JSObject> holder_obj, Runtime::FunctionId id) {
223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(NamedLoadHandlerCompiler::kInterceptorArgsLength ==
224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         Runtime::FunctionForId(id)->nargs);
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CallRuntime(id);
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Generate call to api function.
231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid PropertyHandlerCompiler::GenerateApiAccessorCall(
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MacroAssembler* masm, const CallOptimization& optimization,
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Map> receiver_map, Register receiver, Register scratch_in,
234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bool is_store, Register store_parameter, Register accessor_holder,
235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int accessor_index) {
236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!accessor_holder.is(scratch_in));
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!receiver.is(scratch_in));
238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ push(receiver);
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Write the arguments to stack frame.
240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (is_store) {
241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!receiver.is(store_parameter));
242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!scratch_in.is(store_parameter));
243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ push(store_parameter);
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(optimization.is_simple_api_call());
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2471b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  // Abi for CallApiCallbackStub.
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register callee = a0;
249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register data = a4;
250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register holder = a2;
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register api_function_address = a1;
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Put callee in place.
254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadAccessor(callee, accessor_holder, accessor_index,
255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                  is_store ? ACCESSOR_SETTER : ACCESSOR_GETTER);
256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Put holder in place.
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallOptimization::HolderLookup holder_lookup;
259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int holder_depth = 0;
260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  optimization.LookupHolderOfExpectedType(receiver_map, &holder_lookup,
261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                          &holder_depth);
262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (holder_lookup) {
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case CallOptimization::kHolderIsReceiver:
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Move(holder, receiver);
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case CallOptimization::kHolderFound:
267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ ld(holder, FieldMemOperand(receiver, HeapObject::kMapOffset));
268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ ld(holder, FieldMemOperand(holder, Map::kPrototypeOffset));
269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      for (int i = 1; i < holder_depth; i++) {
270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ ld(holder, FieldMemOperand(holder, HeapObject::kMapOffset));
271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ ld(holder, FieldMemOperand(holder, Map::kPrototypeOffset));
272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case CallOptimization::kHolderNotFound:
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNREACHABLE();
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = masm->isolate();
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool call_data_undefined = false;
282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Put call data in place.
28321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  if (api_call_info->data()->IsUndefined(isolate)) {
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    call_data_undefined = true;
285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ LoadRoot(data, Heap::kUndefinedValueRootIndex);
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
287342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch    if (optimization.is_constant_call()) {
288342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch      __ ld(data,
289342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch            FieldMemOperand(callee, JSFunction::kSharedFunctionInfoOffset));
290342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch      __ ld(data,
291342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch            FieldMemOperand(data, SharedFunctionInfo::kFunctionDataOffset));
292342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch      __ ld(data, FieldMemOperand(data, FunctionTemplateInfo::kCallCodeOffset));
293342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch    } else {
294342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch      __ ld(data,
295342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch            FieldMemOperand(callee, FunctionTemplateInfo::kCallCodeOffset));
296342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch    }
297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ ld(data, FieldMemOperand(data, CallHandlerInfo::kDataOffset));
298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (api_call_info->fast_handler()->IsCode()) {
301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Just tail call into the fast handler if present.
302014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Jump(handle(Code::cast(api_call_info->fast_handler())),
303014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            RelocInfo::CODE_TARGET);
304014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Put api_function_address in place.
307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address function_address = v8::ToCData<Address>(api_call_info->callback());
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ApiFunction fun(function_address);
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference::Type type = ExternalReference::DIRECT_API_CALL;
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference ref = ExternalReference(&fun, type, masm->isolate());
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ li(api_function_address, Operand(ref));
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Jump to stub.
3141b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  CallApiCallbackStub stub(isolate, is_store, call_data_undefined,
315342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch                           !optimization.is_constant_call());
316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ TailCallStub(&stub);
317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic void StoreIC_PushArgs(MacroAssembler* masm) {
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(),
322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          StoreDescriptor::ValueRegister(),
323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          VectorStoreICDescriptor::SlotRegister(),
324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          VectorStoreICDescriptor::VectorRegister());
325014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
326014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
327014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
328014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid NamedStoreHandlerCompiler::GenerateSlow(MacroAssembler* masm) {
329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  StoreIC_PushArgs(masm);
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The slow case calls into the runtime to complete the store without causing
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // an IC miss that would otherwise cause a transition to the generic stub.
333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ TailCallRuntime(Runtime::kStoreIC_Slow);
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) {
338014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  StoreIC_PushArgs(masm);
339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The slow case calls into the runtime to complete the store without causing
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // an IC miss that would otherwise cause a transition to the generic stub.
342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow);
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ ACCESS_MASM(masm())
348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                    Handle<Name> name) {
352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!label->is_unused()) {
353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(label);
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ li(this->name(), Operand(name));
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
359958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) {
360958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ li(this->name(), Operand(name));
361958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
364014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid NamedStoreHandlerCompiler::RearrangeVectorAndSlot(
365014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register current_map, Register destination_map) {
366014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(false);  // Not implemented.
367014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
369014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
370958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition,
371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                   Register map_reg,
372958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                   Register scratch,
373958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                   Label* miss) {
374958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<WeakCell> cell = Map::WeakCellForMap(transition);
375958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!map_reg.is(scratch));
376958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadWeakValue(map_reg, cell, miss);
377958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (transition->CanBeDeprecated()) {
378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ lwu(scratch, FieldMemOperand(map_reg, Map::kBitField3Offset));
379958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ And(at, scratch, Operand(Map::Deprecated::kMask));
380958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ Branch(miss, ne, at, Operand(zero_reg));
381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
382958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
385958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedStoreHandlerCompiler::GenerateConstantCheck(Register map_reg,
386958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                      int descriptor,
387958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                      Register value_reg,
388958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                      Register scratch,
389958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                      Label* miss_label) {
390958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!map_reg.is(scratch));
391958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!map_reg.is(value_reg));
392958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!value_reg.is(scratch));
393958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadInstanceDescriptors(map_reg, scratch);
394958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ ld(scratch,
395958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        FieldMemOperand(scratch, DescriptorArray::GetValueOffset(descriptor)));
396958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Branch(miss_label, ne, value_reg, Operand(scratch));
397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
399342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdochvoid NamedStoreHandlerCompiler::GenerateFieldTypeChecks(FieldType* field_type,
400958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                        Register value_reg,
401958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                        Label* miss_label) {
402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register map_reg = scratch1();
403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register scratch = scratch2();
404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!value_reg.is(map_reg));
405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!value_reg.is(scratch));
406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfSmi(value_reg, miss_label);
407342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  if (field_type->IsClass()) {
408014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ ld(map_reg, FieldMemOperand(value_reg, HeapObject::kMapOffset));
409342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch    // Compare map directly within the Branch() functions.
410342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch    __ GetWeakValue(scratch, Map::WeakCellForMap(field_type->AsClass()));
411342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch    __ Branch(miss_label, ne, map_reg, Operand(scratch));
412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister PropertyHandlerCompiler::CheckPrototypes(
417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object_reg, Register holder_reg, Register scratch1,
418014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register scratch2, Handle<Name> name, Label* miss, PrototypeCheckType check,
419014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ReturnHolder return_what) {
420014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<Map> receiver_map = map();
421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Make sure there's no overlap between holder and object registers.
423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) &&
425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         !scratch2.is(scratch1));
426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
42721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  Handle<Cell> validity_cell =
42821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
42921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  if (!validity_cell.is_null()) {
43021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value());
43121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    __ li(scratch1, Operand(validity_cell));
43221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    __ ld(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset));
43321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    __ Branch(miss, ne, scratch1,
43421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch              Operand(Smi::FromInt(Map::kPrototypeChainValid)));
43521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
436014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
43721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  // The prototype chain of primitives (and their JSValue wrappers) depends
43821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  // on the native context, which can't be guarded by validity cells.
43921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  // |object_reg| holds the native context specific prototype in this case;
44021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  // we need to check its map.
44121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  if (check == CHECK_ALL_MAPS) {
44221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    __ ld(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset));
44321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
44421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    __ GetWeakValue(scratch2, cell);
44521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    __ Branch(miss, ne, scratch1, Operand(scratch2));
446014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
447014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Keep track of the current object in register reg.
449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register reg = object_reg;
450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int depth = 0;
451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<JSObject> current = Handle<JSObject>::null();
453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (receiver_map->IsJSGlobalObjectMap()) {
454014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    current = isolate()->global_object();
455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
456014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
457014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Check access rights to the global object.  This has to happen after
458014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // the map check so that we know that the object is actually a global
459014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // object.
460014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // This allows us to install generated handlers for accesses to the
461014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // global proxy (as opposed to using slow ICs). See corresponding code
462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // in LookupForRead().
463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (receiver_map->IsJSGlobalProxyMap()) {
464014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CheckAccessGlobalProxy(reg, scratch2, miss);
465014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
466014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben 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()));
48121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    if (current_map->IsJSGlobalObjectMap()) {
48221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
48321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch                                name, scratch2, miss);
48421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    } else if (current_map->is_dictionary_map()) {
485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!current_map->IsJSGlobalProxyMap());  // Proxy maps are fast.
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (!name->IsUniqueName()) {
487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(name->IsString());
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        name = factory()->InternalizeString(Handle<String>::cast(name));
489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(current.is_null() ||
491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             current->property_dictionary()->FindEntry(name) ==
492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 NameDictionary::kNotFound);
493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
49421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      if (depth > 1) {
495014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // TODO(jkummerow): Cache and re-use weak cell.
496014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1,
499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       scratch2);
500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
502014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    reg = holder_reg;  // From now on the object will be in holder_reg.
503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Go to the next object in the prototype chain.
504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    current = prototype;
505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    current_map = handle(current->map());
506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!current_map->IsJSGlobalProxyMap());
509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Log the check depth.
511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
513014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool return_holder = return_what == RETURN_HOLDER;
51421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  if (return_holder && depth != 0) {
515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Return the register containing the holder.
519014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return return_holder ? reg : no_reg;
520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!miss->is_unused()) {
525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label success;
526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Branch(&success);
527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(miss);
528958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (IC::ICUseVector(kind())) {
529958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      DCHECK(kind() == Code::LOAD_IC);
530958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      PopVectorAndSlot();
531958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TailCallBuiltin(masm(), MissBuiltin(kind()));
533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&success);
534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!miss->is_unused()) {
540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label success;
541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Branch(&success);
542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    GenerateRestoreName(miss, name);
543014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (IC::ICUseVector(kind())) PopVectorAndSlot();
544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TailCallBuiltin(masm(), MissBuiltin(kind()));
545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&success);
546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) {
551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Return the constant value.
552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ li(v0, value);
553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Ret();
554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LookupIterator* it, Register holder_reg) {
559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(holder()->HasNamedInterceptor());
56021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate()));
561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Compile the interceptor call, followed by inline code to load the
563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // property from further up the prototype chain if the call fails.
564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that the maps haven't changed.
565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1()));
566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Preserve the receiver register explicitly whenever it is different from the
568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // holder and it is needed should the interceptor return without any result.
569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The ACCESSOR case needs the receiver to be passed into C++ code, the FIELD
570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // case might cause a miss during the prototype check.
571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool must_perform_prototype_check =
572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      !holder().is_identical_to(it->GetHolder<JSObject>());
573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool must_preserve_receiver_reg =
574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      !receiver().is(holder_reg) &&
575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      (it->state() == LookupIterator::ACCESSOR || must_perform_prototype_check);
576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Save necessary data before invoking an interceptor.
578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Requires a frame to make GC aware of pushed pointers.
579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FrameScope frame_scope(masm(), StackFrame::INTERNAL);
581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (must_preserve_receiver_reg) {
582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(receiver(), holder_reg, this->name());
583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(holder_reg, this->name());
585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
586958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    InterceptorVectorSlotPush(holder_reg);
587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Invoke an interceptor.  Note: map checks from receiver to
588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // interceptor's holder has been compiled before (see a caller
589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // of this method).
590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileCallLoadPropertyWithInterceptor(
591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        masm(), receiver(), holder_reg, this->name(), holder(),
592014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Runtime::kLoadPropertyWithInterceptorOnly);
593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Check if interceptor provided a value for property.  If it's
595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // the case, return immediately.
596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label interceptor_failed;
597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex);
598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Branch(&interceptor_failed, eq, v0, Operand(scratch1()));
599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    frame_scope.GenerateLeaveFrame();
600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Ret();
601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&interceptor_failed);
603958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    InterceptorVectorSlotPop(holder_reg);
604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (must_preserve_receiver_reg) {
605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pop(receiver(), holder_reg, this->name());
606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pop(holder_reg, this->name());
608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Leave the internal frame.
610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenerateLoadPostInterceptor(it, holder_reg);
613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) {
617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Call the runtime system to load the interceptor.
618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(holder()->HasNamedInterceptor());
61921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate()));
620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(),
621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           holder());
622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
623014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ TailCallRuntime(Runtime::kLoadPropertyWithInterceptor);
624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
628342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch    Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> callback,
629342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch    LanguageMode language_mode) {
630958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register holder_reg = Frontend(name);
631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(receiver(), holder_reg);  // Receiver.
633014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // If the callback cannot leak, then push the callback directly,
634014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // otherwise wrap it in a weak cell.
63521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  if (callback->data()->IsUndefined(isolate()) || callback->data()->IsSmi()) {
636014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ li(at, Operand(callback));
637014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
638014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Handle<WeakCell> cell = isolate()->factory()->NewWeakCell(callback);
639014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ li(at, Operand(cell));
640014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ push(at);
642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ li(at, Operand(name));
643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(at, value());
644342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  __ Push(Smi::FromInt(language_mode));
645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Do tail-call to the runtime system.
647014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ TailCallRuntime(Runtime::kStoreCallbackProperty);
648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Return the generated code.
650537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch  return GetCode(kind(), name);
651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister NamedStoreHandlerCompiler::value() {
655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return StoreDescriptor::ValueRegister();
656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) {
661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label miss;
662958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (IC::ICUseVector(kind())) {
663958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    PushVectorAndSlot();
664958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
666014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FrontendHeader(receiver(), name, &miss, DONT_RETURN_ANYTHING);
667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the value from the cell.
669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = StoreDescriptor::ValueRegister();
670958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell);
671958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadWeakValue(result, weak_cell, &miss);
672014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ ld(result, FieldMemOperand(result, PropertyCell::kValueOffset));
673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for deleted property if property can actually be deleted.
675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (is_configurable) {
676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Branch(&miss, eq, result, Operand(at));
678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Counters* counters = isolate()->counters();
681342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  __ IncrementCounter(counters->ic_named_load_global_stub(), 1, a1, a3);
682958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (IC::ICUseVector(kind())) {
683958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DiscardVectorAndSlot();
684958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Ret(USE_DELAY_SLOT);
686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(v0, result);
687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FrontendFooter(name, &miss);
689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Return the generated code.
691537ba893e2530051ec7f296e769fdd37bb4ae4a0Ben Murdoch  return GetCode(kind(), name);
692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __
696014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // V8_TARGET_ARCH_MIPS64
700