stub-cache-arm.cc revision d0582a6c46733687d045e4188a1bcd0123c758a1
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2006-2009 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "ic-inl.h"
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "codegen-inl.h"
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "stub-cache.h"
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm)
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void ProbeTable(MacroAssembler* masm,
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       Code::Flags flags,
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       StubCache::Table table,
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       Register name,
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       Register offset) {
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference key_offset(SCTableReference::keyReference(table));
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference value_offset(SCTableReference::valueReference(table));
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Save the offset on the stack.
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(offset);
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the key in the entry matches the name.
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(ip, Operand(key_offset));
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(ip, MemOperand(ip, offset, LSL, 1));
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(name, Operand(ip));
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the code entry from the cache.
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(ip, Operand(value_offset));
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(offset, MemOperand(ip, offset, LSL, 1));
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the flags match what we're looking for.
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(offset, FieldMemOperand(offset, Code::kFlagsOffset));
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(offset, offset, Operand(~Code::kFlagsNotUsedInLookup));
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(offset, Operand(flags));
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Restore offset and re-load code entry from cache.
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(offset);
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(ip, Operand(value_offset));
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(offset, MemOperand(ip, offset, LSL, 1));
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the first instruction in the code stub.
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(offset, offset, Operand(Code::kHeaderSize - kHeapObjectTag));
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(offset);
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Miss: Restore offset and fall through.
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(offset);
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCache::GenerateProbe(MacroAssembler* masm,
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Code::Flags flags,
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Register receiver,
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Register name,
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Register scratch,
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Register extra) {
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that code is valid. The shifting code relies on the
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // entry size being 8.
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(sizeof(Entry) == 8);
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure the flags does not name a specific type.
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that there are no register conflicts.
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!scratch.is(receiver));
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!scratch.is(name));
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(receiver, Operand(kSmiTagMask));
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &miss);
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the map of the receiver and compute the hash.
108d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ ldr(scratch, FieldMemOperand(name, String::kHashFieldOffset));
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(ip, FieldMemOperand(receiver, HeapObject::kMapOffset));
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(scratch, scratch, Operand(ip));
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ eor(scratch, scratch, Operand(flags));
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(scratch,
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          scratch,
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          Operand((kPrimaryTableSize - 1) << kHeapObjectTagSize));
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Probe the primary table.
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ProbeTable(masm, flags, kPrimary, name, scratch);
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Primary miss: Compute hash for secondary probe.
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ sub(scratch, scratch, Operand(name));
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(scratch, scratch, Operand(flags));
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(scratch,
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          scratch,
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          Operand((kSecondaryTableSize - 1) << kHeapObjectTagSize));
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Probe the secondary table.
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ProbeTable(masm, flags, kSecondary, name, scratch);
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Cache miss: Fall-through and let caller handle the miss by
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // entering the runtime system.
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                       int index,
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                       Register prototype) {
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the global or builtins object from the current context.
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the global context from the global or builtins object.
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(prototype,
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         FieldMemOperand(prototype, GlobalObject::kGlobalContextOffset));
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the function from the global context.
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(prototype, MemOperand(prototype, Context::SlotOffset(index)));
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the initial map.  The global functions all have initial maps.
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(prototype,
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         FieldMemOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the prototype from the initial map.
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset));
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Load a fast property out of a holder object (src). In-object properties
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// are loaded directly otherwise the property is loaded from the properties
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// fixed array.
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Register dst, Register src,
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            JSObject* holder, int index) {
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adjust for the number of properties stored in the holder.
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  index -= holder->map()->inobject_properties();
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (index < 0) {
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Get the property straight out of the holder.
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = holder->map()->instance_size() + (index * kPointerSize);
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(dst, FieldMemOperand(src, offset));
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Calculate the offset into the properties array.
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = index * kPointerSize + FixedArray::kHeaderSize;
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(dst, FieldMemOperand(src, JSObject::kPropertiesOffset));
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(dst, FieldMemOperand(dst, offset));
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register receiver,
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register scratch,
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Label* miss_label) {
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(receiver, Operand(kSmiTagMask));
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, miss_label);
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object is a JS array.
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE);
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, miss_label);
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load length directly from the JS array.
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Ret();
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate code to check if an object is a string.  If the object is
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// a string, the map's instance type is left in the scratch1 register.
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GenerateStringCheck(MacroAssembler* masm,
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Register receiver,
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Register scratch1,
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Register scratch2,
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Label* smi,
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Label* non_string_object) {
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(receiver, Operand(kSmiTagMask));
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, smi);
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object is a string.
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(scratch2, scratch1, Operand(kIsNotStringMask));
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The cast is to resolve the overload for the argument of 0x0.
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag)));
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, non_string_object);
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate code to load the length from a string object and return the length.
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// If the receiver object is not a string or a wrapped string object the
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// execution continues at the miss label. The register containing the
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// receiver is potentially clobbered.
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadStringLength2(MacroAssembler* masm,
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register receiver,
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register scratch1,
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Register scratch2,
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Label* miss) {
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label check_string, check_wrapper;
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&check_string);
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if the object is a string leaving the instance type in the
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch1 register.
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateStringCheck(masm, receiver, scratch1, scratch2,
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      miss, &check_wrapper);
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load length directly from the string.
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, FieldMemOperand(receiver, String::kLengthOffset));
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(r0, LSL, kSmiTagSize));
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Ret();
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if the object is a JSValue wrapper.
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&check_wrapper);
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(scratch1, Operand(JS_VALUE_TYPE));
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, miss);
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Unwrap the value in place and check if the wrapped value is a string.
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(receiver, FieldMemOperand(receiver, JSValue::kValueOffset));
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(&check_string);
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 Register receiver,
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 Register scratch1,
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 Register scratch2,
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 Label* miss_label) {
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, scratch1);
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Ret();
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate StoreField code, value is passed in r0 register.
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// After executing generated code, the receiver_reg and name_reg
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// may be clobbered.
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateStoreField(MacroAssembler* masm,
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Builtins::Name storage_extend,
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      JSObject* object,
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      int index,
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Map* transition,
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register receiver_reg,
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register name_reg,
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register scratch,
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Label* miss_label) {
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0 : value
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label exit;
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(receiver_reg, Operand(kSmiTagMask));
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, miss_label);
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the receiver hasn't changed.
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(scratch, Operand(Handle<Map>(object->map())));
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, miss_label);
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform global security token check if needed.
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsJSGlobalProxy()) {
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub never generated for non-global objects that require access
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // checks.
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform map transition for the receiver if necessary.
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The properties must be extended before we can store the value.
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // We jump to a runtime call that extends the properties array.
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r2, Operand(Handle<Map>(transition)));
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Please note, if we implement keyed store for arm we need
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // to call the Builtins::KeyedStoreIC_ExtendStorage.
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_ExtendStorage));
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Jump(ic, RelocInfo::CODE_TARGET);
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (transition != NULL) {
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Update the map of the object; no write barrier updating is
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // needed because the map is never in new space.
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(ip, Operand(Handle<Map>(transition)));
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(ip, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adjust for the number of properties stored in the object. Even in the
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // face of a transition we can use the old map here because the size of the
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object and the number of in-object properties is not going to change.
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  index -= object->map()->inobject_properties();
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (index < 0) {
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Set the property straight into the object.
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = object->map()->instance_size() + (index * kPointerSize);
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r0, FieldMemOperand(receiver_reg, offset));
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Skip updating write barrier if storing a smi.
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r0, Operand(kSmiTagMask));
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &exit);
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Update the write barrier for the array address.
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Pass the value being stored in the now unused name_reg.
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(name_reg, Operand(offset));
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ RecordWrite(receiver_reg, name_reg, scratch);
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Write to the properties array.
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = index * kPointerSize + FixedArray::kHeaderSize;
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Get the properties array
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(scratch, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r0, FieldMemOperand(scratch, offset));
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Skip updating write barrier if storing a smi.
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r0, Operand(kSmiTagMask));
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &exit);
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Update the write barrier for the array address.
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Ok to clobber receiver_reg and name_reg, since we return.
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(name_reg, Operand(offset));
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ RecordWrite(scratch, name_reg, receiver_reg);
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the value (register r0).
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&exit);
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Ret();
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Code* code = NULL;
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (kind == Code::LOAD_IC) {
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    code = Builtins::builtin(Builtins::LoadIC_Miss);
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> ic(code);
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm())
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister StubCompiler::CheckPrototypes(JSObject* object,
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       Register object_reg,
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       JSObject* holder,
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       Register holder_reg,
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       Register scratch,
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       String* name,
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       Label* miss) {
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the maps haven't changed.
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Register result =
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      masm()->CheckMaps(object, object_reg, holder, holder_reg, scratch, miss);
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If we've skipped any global objects, it's not enough to verify
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // that their maps haven't changed.
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (object != holder) {
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (object->IsGlobalObject()) {
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      GlobalObject* global = GlobalObject::cast(object);
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Object* probe = global->EnsurePropertyCell(name);
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (probe->IsFailure()) {
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        set_failure(Failure::cast(probe));
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return result;
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe);
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(cell->value()->IsTheHole());
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ mov(scratch, Operand(Handle<Object>(cell)));
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ ldr(scratch,
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ cmp(scratch, ip);
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(ne, miss);
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    object = JSObject::cast(object->GetPrototype());
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the register containin the holder.
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result;
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadField(JSObject* object,
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     JSObject* holder,
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Register receiver,
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Register scratch1,
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Register scratch2,
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     int index,
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     String* name,
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Label* miss) {
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(receiver, Operand(kSmiTagMask));
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, miss);
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the maps haven't changed.
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Register reg =
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CheckPrototypes(object, receiver, holder, scratch1, scratch2, name, miss);
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateFastPropertyLoad(masm(), r0, reg, holder, index);
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Ret();
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadConstant(JSObject* object,
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        JSObject* holder,
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register receiver,
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch1,
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch2,
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Object* value,
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        String* name,
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Label* miss) {
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(receiver, Operand(kSmiTagMask));
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, miss);
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the maps haven't changed.
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Register reg =
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CheckPrototypes(object, receiver, holder, scratch1, scratch2, name, miss);
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the constant value.
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(Handle<Object>(value)));
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Ret();
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadCallback(JSObject* object,
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        JSObject* holder,
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register receiver,
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register name_reg,
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch1,
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch2,
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        AccessorInfo* callback,
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        String* name,
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Label* miss) {
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(receiver, Operand(kSmiTagMask));
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, miss);
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the maps haven't changed.
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Register reg =
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CheckPrototypes(object, receiver, holder, scratch1, scratch2, name, miss);
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Push the arguments on the JS stack of the caller.
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(receiver);  // receiver
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(reg);  // holder
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(ip, Operand(Handle<AccessorInfo>(callback)));  // callback data
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ip);
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(reg, FieldMemOperand(ip, AccessorInfo::kDataOffset));
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(reg);
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(name_reg);  // name
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do tail-call to the runtime system.
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference load_callback_property =
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ TailCallRuntime(load_callback_property, 5, 1);
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadInterceptor(JSObject* object,
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           JSObject* holder,
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           LookupResult* lookup,
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register receiver,
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register name_reg,
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register scratch1,
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register scratch2,
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           String* name,
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Label* miss) {
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(receiver, Operand(kSmiTagMask));
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, miss);
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the maps haven't changed.
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Register reg =
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CheckPrototypes(object, receiver, holder, scratch1, scratch2, name, miss);
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Push the arguments on the JS stack of the caller.
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(receiver);  // receiver
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(reg);  // holder
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(name_reg);  // name
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InterceptorInfo* interceptor = holder->GetNamedInterceptor();
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!Heap::InNewSpace(interceptor));
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(scratch1, Operand(Handle<Object>(interceptor)));
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(scratch1);
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(scratch2, FieldMemOperand(scratch1, InterceptorInfo::kDataOffset));
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(scratch2);
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do tail-call to the runtime system.
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference load_ic_property =
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad));
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ TailCallRuntime(load_ic_property, 5, 1);
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* StubCompiler::CompileLazyCompile(Code::Flags flags) {
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r1: function
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr: return address
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Enter an internal frame.
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ EnterInternalFrame();
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Preserve the function.
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r1);
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Push the function on the stack as the argument to the runtime function.
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r1);
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CallRuntime(Runtime::kLazyCompile, 1);
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate the entry point.
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Restore saved function.
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(r1);
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Tear down temporary frame.
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LeaveInternalFrame();
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do a tail-call of the compiled function.
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(r2);
545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCodeWithFlags(flags, "LazyCompileStub");
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* CallStubCompiler::CompileCallField(Object* object,
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           JSObject* holder,
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           int index,
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           String* name) {
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr: return address
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver of the function from the stack into r0.
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(sp, argc * kPointerSize));
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(r0, Operand(kSmiTagMask));
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &miss);
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do the right check and compute the holder register.
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Register reg =
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CheckPrototypes(JSObject::cast(object), r0, holder, r3, r2, name, &miss);
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateFastPropertyLoad(masm(), r1, reg, holder, index);
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the function really is a function.
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(r1, Operand(kSmiTagMask));
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &miss);
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the map.
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the receiver on the stack with the global proxy if
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // necessary.
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsGlobalObject()) {
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r3, MemOperand(sp, argc * kPointerSize));
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the function.
587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ InvokeFunction(r1, arguments(), JUMP_FUNCTION);
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> ic = ComputeCallMiss(arguments().immediate());
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(FIELD, name);
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* CallStubCompiler::CompileCallConstant(Object* object,
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              JSObject* holder,
601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              JSFunction* function,
602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              String* name,
603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              CheckType check) {
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr: return address
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver from the stack
610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(sp, argc * kPointerSize));
612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (check != NUMBER_CHECK) {
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r1, Operand(kSmiTagMask));
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &miss);
617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that it's okay not to patch the on stack receiver
620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // unless we're doing a receiver map check.
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (check) {
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case RECEIVER_MAP_CHECK:
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Check that the maps haven't changed.
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CheckPrototypes(JSObject::cast(object), r1, holder, r3, r2, name, &miss);
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Patch the receiver on the stack with the global proxy if
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // necessary.
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (object->IsGlobalObject()) {
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        __ str(r3, MemOperand(sp, argc * kPointerSize));
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case STRING_CHECK:
637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Check that the object is a two-byte string or a symbol.
638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ CompareObjectType(r1, r2, r2, FIRST_NONSTRING_TYPE);
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(hs, &miss);
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Check that the maps starting from the prototype haven't changed.
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      GenerateLoadGlobalFunctionPrototype(masm(),
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                          Context::STRING_FUNCTION_INDEX,
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                          r2);
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CheckPrototypes(JSObject::cast(object->GetPrototype()), r2, holder, r3,
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      r1, name, &miss);
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case NUMBER_CHECK: {
649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Label fast;
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Check that the object is a smi or a heap number.
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ tst(r1, Operand(kSmiTagMask));
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(eq, &fast);
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ CompareObjectType(r1, r2, r2, HEAP_NUMBER_TYPE);
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(ne, &miss);
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ bind(&fast);
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Check that the maps starting from the prototype haven't changed.
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      GenerateLoadGlobalFunctionPrototype(masm(),
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                          Context::NUMBER_FUNCTION_INDEX,
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                          r2);
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CheckPrototypes(JSObject::cast(object->GetPrototype()), r2, holder, r3,
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      r1, name, &miss);
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case BOOLEAN_CHECK: {
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Label fast;
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Check that the object is a boolean.
668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ LoadRoot(ip, Heap::kTrueValueRootIndex);
669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ cmp(r1, ip);
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(eq, &fast);
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ LoadRoot(ip, Heap::kFalseValueRootIndex);
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ cmp(r1, ip);
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(ne, &miss);
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ bind(&fast);
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Check that the maps starting from the prototype haven't changed.
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      GenerateLoadGlobalFunctionPrototype(masm(),
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                          Context::BOOLEAN_FUNCTION_INDEX,
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                          r2);
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CheckPrototypes(JSObject::cast(object->GetPrototype()), r2, holder, r3,
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      r1, name, &miss);
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CheckPrototypes(JSObject::cast(object), r1, holder, r3, r2, name, &miss);
686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Make sure object->HasFastElements().
687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Get the elements array of the object.
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ ldr(r3, FieldMemOperand(r1, JSObject::kElementsOffset));
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Check that the object is in fast mode (not dictionary).
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ cmp(r2, ip);
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(ne, &miss);
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNREACHABLE();
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the function and setup the context.
701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r1, Operand(Handle<JSFunction>(function)));
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the cached code (tail call).
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(function->is_compiled());
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> code(function->code());
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount expected(function->shared()->formal_parameter_count());
708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ InvokeCode(code, expected, arguments(),
709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                RelocInfo::CODE_TARGET, JUMP_FUNCTION);
710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> ic = ComputeCallMiss(arguments().immediate());
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  String* function_name = NULL;
718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (function->shared()->name()->IsString()) {
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    function_name = String::cast(function->shared()->name());
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CONSTANT_FUNCTION, function_name);
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* CallStubCompiler::CompileCallInterceptor(Object* object,
726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 JSObject* holder,
727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 String* name) {
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr: return address
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // TODO(1224669): Implement.
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> ic = ComputeCallMiss(arguments().immediate());
738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* CallStubCompiler::CompileCallGlobal(JSObject* object,
746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            GlobalObject* holder,
747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            JSGlobalPropertyCell* cell,
748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            JSFunction* function,
749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            String* name) {
750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr: return address
752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the number of arguments.
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver from the stack.
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(sp, argc * kPointerSize));
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the object is the holder then we know that it's a global
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object which can only happen for contextual calls. In this case,
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the receiver cannot be a smi.
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object != holder) {
765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r0, Operand(kSmiTagMask));
766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &miss);
767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the maps haven't changed.
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckPrototypes(object, r0, holder, r3, r2, name, &miss);
771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the value from the cell.
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell)));
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset));
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the cell contains the same function.
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r1, Operand(Handle<JSFunction>(function)));
778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the receiver on the stack with the global proxy if
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // necessary.
782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsGlobalObject()) {
783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r3, MemOperand(sp, argc * kPointerSize));
785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Setup the context (function already in r1).
788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the cached code (tail call).
791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::call_global_inline, 1, r2, r3);
792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(function->is_compiled());
793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> code(function->code());
794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount expected(function->shared()->formal_parameter_count());
795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ InvokeCode(code, expected, arguments(),
796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                RelocInfo::CODE_TARGET, JUMP_FUNCTION);
797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::call_global_inline_miss, 1, r1, r3);
801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> ic = ComputeCallMiss(arguments().immediate());
802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(NORMAL, name);
806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* StoreStubCompiler::CompileStoreField(JSObject* object,
810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             int index,
811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             Map* transition,
812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             String* name) {
813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0    : value
815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- [sp]  : receiver
818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver from the stack.
822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // name register might be clobbered.
825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateStoreField(masm(),
826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     Builtins::StoreIC_ExtendStorage,
827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     object,
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     index,
829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     transition,
830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     r3, r2, r1,
831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     &miss);
832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r2, Operand(Handle<String>(name)));  // restore name
834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* StoreStubCompiler::CompileStoreCallback(JSObject* object,
843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                AccessorInfo* callback,
844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                String* name) {
845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0    : value
847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- [sp]  : receiver
850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the object from the stack.
854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object isn't a smi.
857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(r3, Operand(kSmiTagMask));
858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &miss);
859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the object hasn't changed.
861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r1, Operand(Handle<Map>(object->map())));
863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform global security token check if needed.
866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsJSGlobalProxy()) {
867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ CheckAccessGlobalProxy(r3, r1, &miss);
868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub never generated for non-global objects that require access
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // checks.
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(ip, MemOperand(sp));  // receiver
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ip);
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(ip, Operand(Handle<AccessorInfo>(callback)));  // callback info
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ip);
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r2);  // name
879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);  // value
880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do tail-call to the runtime system.
882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference store_callback_property =
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ TailCallRuntime(store_callback_property, 4, 1);
885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r2, Operand(Handle<String>(name)));  // restore name
889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                   String* name) {
899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0    : value
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- [sp]  : receiver
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the object from the stack.
908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object isn't a smi.
911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(r3, Operand(kSmiTagMask));
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &miss);
913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the object hasn't changed.
915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r1, Operand(Handle<Map>(receiver->map())));
917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform global security token check if needed.
920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (receiver->IsJSGlobalProxy()) {
921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ CheckAccessGlobalProxy(r3, r1, &miss);
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub never generated for non-global objects that require access
925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // checks.
926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(ip, MemOperand(sp));  // receiver
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ip);
930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r2);  // name
931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);  // value
932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do tail-call to the runtime system.
934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference store_ic_property =
935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ TailCallRuntime(store_ic_property, 3, 1);
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r2, Operand(Handle<String>(name)));  // restore name
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              JSGlobalPropertyCell* cell,
951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              String* name) {
952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0    : value
954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- [sp]  : receiver
957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the global has not changed.
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(sp, 0 * kPointerSize));
962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r3, Operand(Handle<Map>(object->map())));
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Store the value in the cell.
967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r2, Operand(Handle<JSGlobalPropertyCell>(cell)));
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(r0, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::named_store_global_inline, 1, r1, r3);
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Ret();
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::named_store_global_inline_miss, 1, r1, r3);
976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(NORMAL, name);
981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* LoadStubCompiler::CompileLoadField(JSObject* object,
985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           JSObject* holder,
986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           int index,
987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           String* name) {
988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- [sp]  : receiver
992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(sp, 0));
996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadField(object, holder, r0, r3, r1, index, name, &miss);
998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(FIELD, name);
1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* LoadStubCompiler::CompileLoadCallback(JSObject* object,
1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              JSObject* holder,
1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              AccessorInfo* callback,
1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              String* name) {
1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- [sp]  : receiver
1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(sp, 0));
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadCallback(object, holder, r0, r2, r3, r1, callback, name, &miss);
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* LoadStubCompiler::CompileLoadConstant(JSObject* object,
1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              JSObject* holder,
1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              Object* value,
1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              String* name) {
1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- [sp] : receiver
1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(sp, 0));
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadConstant(object, holder, r0, r3, r1, value, name, &miss);
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CONSTANT_FUNCTION, name);
1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* object,
1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 JSObject* holder,
1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 String* name) {
1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- [sp]  : receiver
1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(sp, 0));
1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LookupResult lookup;
1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  holder->LocalLookupRealNamedProperty(name, &lookup);
1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadInterceptor(object,
1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          holder,
1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          &lookup,
1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          r0,
1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          r2,
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          r3,
1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          r1,
1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          name,
1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          &miss);
1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            GlobalObject* holder,
1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            JSGlobalPropertyCell* cell,
1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            String* name,
1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            bool is_dont_delete) {
1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- [sp]  : receiver
1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver from the stack.
1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(sp, 0 * kPointerSize));
1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the object is the holder then we know that it's a global
1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object which can only happen for contextual calls. In this case,
1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the receiver cannot be a smi.
1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object != holder) {
1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r1, Operand(kSmiTagMask));
1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &miss);
1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the global has not changed.
1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckPrototypes(object, r1, holder, r3, r0, name, &miss);
1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the value from the cell.
1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell)));
1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset));
1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for deleted property if property can actually be deleted.
1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!is_dont_delete) {
1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r0, ip);
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &miss);
1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::named_load_global_inline, 1, r1, r3);
1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Ret();
1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::named_load_global_inline_miss, 1, r1, r3);
1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(NORMAL, name);
1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadField(String* name,
1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                JSObject* receiver,
1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                JSObject* holder,
1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                int index) {
1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- sp[0] : key
1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- sp[4] : receiver
1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, MemOperand(sp, 0));
1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(sp, kPointerSize));
1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r2, Operand(Handle<String>(name)));
1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadField(receiver, holder, r0, r3, r1, index, name, &miss);
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(FIELD, name);
1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                   JSObject* receiver,
1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                   JSObject* holder,
1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                   AccessorInfo* callback) {
1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- sp[0] : key
1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- sp[4] : receiver
1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, MemOperand(sp, 0));
1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(sp, kPointerSize));
1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r2, Operand(Handle<String>(name)));
1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadCallback(receiver, holder, r0, r2, r3, r1, callback, name, &miss);
1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                   JSObject* receiver,
1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                   JSObject* holder,
1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                   Object* value) {
1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- sp[0] : key
1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- sp[4] : receiver
1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the key is the cached one
1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, MemOperand(sp, 0));
1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(sp, kPointerSize));
1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r2, Operand(Handle<String>(name)));
1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadConstant(receiver, holder, r0, r3, r1, value, name, &miss);
1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CONSTANT_FUNCTION, name);
1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                      JSObject* holder,
1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                      String* name) {
1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- sp[0] : key
1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- sp[4] : receiver
1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the key is the cached one
1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, MemOperand(sp, 0));
1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(sp, kPointerSize));
1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r2, Operand(Handle<String>(name)));
1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LookupResult lookup;
1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  holder->LocalLookupRealNamedProperty(name, &lookup);
1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadInterceptor(receiver,
1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          holder,
1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          &lookup,
1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          r0,
1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          r2,
1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          r3,
1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          r1,
1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          name,
1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          &miss);
1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- sp[0] : key
1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- sp[4] : receiver
1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the key is the cached one
1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, MemOperand(sp, 0));
1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(sp, kPointerSize));
1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r2, Operand(Handle<String>(name)));
1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadArrayLength(masm(), r0, r3, &miss);
1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- sp[0] : key
1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- sp[4] : receiver
1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, MemOperand(sp));
1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(sp, kPointerSize));  // receiver
1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r2, Operand(Handle<String>(name)));
1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadStringLength2(masm(), r0, r1, r3, &miss);
1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ DecrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// TODO(1224671): implement the fast case.
1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- sp[0] : key
1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- sp[4] : receiver
1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                  int index,
1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                  Map* transition,
1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                  String* name) {
1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0    : value
1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2    : name
1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- [sp]  : receiver
1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::keyed_store_field, 1, r1, r3);
1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r2, Operand(Handle<String>(name)));
1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &miss);
1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load receiver from the stack.
1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r3, MemOperand(sp));
1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1 is used as scratch register, r3 and r2 might be clobbered.
1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateStoreField(masm(),
1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     Builtins::StoreIC_ExtendStorage,
1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     object,
1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     index,
1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     transition,
1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     r3, r2, r1,
1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     &miss);
1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ DecrementCounter(&Counters::keyed_store_field, 1, r1, r3);
1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r2, Operand(Handle<String>(name)));  // restore name register.
1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(ic, RelocInfo::CODE_TARGET);
1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* ConstructStubCompiler::CompileConstructStub(
1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SharedFunctionInfo* shared) {
1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0    : argc
1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r1    : constructor
1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr    : return address
1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- [sp]  : last argument
1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label generic_stub_call;
1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use r7 for holding undefined which is used in several places below.
1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
1354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check to see whether there are any break points in the function code. If
1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // there are jump to the generic constructor stub which calls the actual
1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // code for the function thereby hitting the break points.
1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kDebugInfoOffset));
1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r2, r7);
1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &generic_stub_call);
1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the initial map and verify that it is in fact a map.
1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r7: undefined
1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(r2, Operand(kSmiTagMask));
1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &generic_stub_call);
1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CompareObjectType(r2, r3, r4, MAP_TYPE);
1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &generic_stub_call);
1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Cannot construct functions this way.
1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: initial map
1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r7: undefined
1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE);
1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Check(ne, "Function constructed by construct stub.");
1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Now allocate the JSObject in new space.
1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: initial map
1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r7: undefined
1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset));
1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ AllocateInNewSpace(r3,
1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        r4,
1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        r5,
1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        r6,
1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        &generic_stub_call,
1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        NO_ALLOCATION_FLAGS);
1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocated the JSObject, now initialize the fields. Map is set to initial
1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // map and properties and elements are set to empty fixed array.
1399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: initial map
1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r3: object size (in words)
1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r4: JSObject (not tagged)
1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r7: undefined
1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex);
1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r5, r4);
1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(r2, MemOperand(r5, kPointerSize, PostIndex));
1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset);
1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate the location of the first argument. The stack contains only the
1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // argc arguments.
1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(r1, sp, Operand(r0, LSL, kPointerSizeLog2));
1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill all the in-object properties with undefined.
1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: first argument
1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r3: object size (in words)
1422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r4: JSObject (not tagged)
1423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r5: First in-object property of JSObject (not tagged)
1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r7: undefined
1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill the initialized properties with a constant value or a passed argument
1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // depending on the this.x = ...; assignment in the function.
1427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < shared->this_property_assignments_count(); i++) {
1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (shared->IsThisPropertyAssignmentArgument(i)) {
1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Label not_passed, next;
1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Check if the argument assigned to the property is actually passed.
1431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int arg_number = shared->GetThisPropertyAssignmentArgument(i);
1432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ cmp(r0, Operand(arg_number));
1433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(le, &not_passed);
1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Argument passed - find it on the stack.
1435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ ldr(r2, MemOperand(r1, (arg_number + 1) * -kPointerSize));
1436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ str(r2, MemOperand(r5, kPointerSize, PostIndex));
1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(&next);
1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ bind(&not_passed);
1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Set the property to undefined.
1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ str(r7, MemOperand(r5, kPointerSize, PostIndex));
1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ bind(&next);
1442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
1443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Set the property to the constant value.
1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i));
1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ mov(r2, Operand(constant));
1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ str(r2, MemOperand(r5, kPointerSize, PostIndex));
1447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill the unused in-object property fields with undefined.
1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = shared->this_property_assignments_count();
1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       i < shared->CalculateInObjectProperties();
1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       i++) {
1454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ str(r7, MemOperand(r5, kPointerSize, PostIndex));
1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r4: JSObject (not tagged)
1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move argc to r1 and the JSObject to return to r0 and tag it.
1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r1, r0);
1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, r4);
1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ orr(r0, r0, Operand(kHeapObjectTag));
1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: JSObject
1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: argc
1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Remove caller arguments and receiver from the stack and return.
1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2));
1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(kPointerSize));
1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::constructed_objects, 1, r1, r2);
1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::constructed_objects_stub, 1, r1, r2);
1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the generic stub in case the specialized code cannot handle the
1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // construction.
1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&generic_stub_call);
1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric);
1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> generic_construct_stub(code);
1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode();
1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __
1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
1488