stub-cache-ia32.cc revision 592a9fc1d8ea420377a2e7efd0600e20b058be2b
18b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// Copyright 2011 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
30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_IA32)
31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "ic-inl.h"
338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "codegen.h"
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "stub-cache.h"
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm)
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic void ProbeTable(Isolate* isolate,
4344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                       MacroAssembler* masm,
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       Code::Flags flags,
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       StubCache::Table table,
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       Register name,
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       Register offset,
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       Register extra) {
4944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference key_offset(isolate->stub_cache()->key_reference(table));
5044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference value_offset(isolate->stub_cache()->value_reference(table));
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (extra.is_valid()) {
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Get the code entry from the cache.
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(extra, Operand::StaticArray(offset, times_2, value_offset));
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Check that the key in the entry matches the name.
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(name, Operand::StaticArray(offset, times_2, key_offset));
60257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(not_equal, &miss);
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Check that the flags match what we're looking for.
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(offset, FieldOperand(extra, Code::kFlagsOffset));
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ and_(offset, ~Code::kFlagsNotUsedInLookup);
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(offset, flags);
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ j(not_equal, &miss);
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Jump to the first instruction in the code stub.
69592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ add(extra, Immediate(Code::kHeaderSize - kHeapObjectTag));
70592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ jmp(extra);
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&miss);
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Save the offset on the stack.
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ push(offset);
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Check that the key in the entry matches the name.
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(name, Operand::StaticArray(offset, times_2, key_offset));
79257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(not_equal, &miss);
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Get the code entry from the cache.
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(offset, Operand::StaticArray(offset, times_2, value_offset));
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Check that the flags match what we're looking for.
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(offset, FieldOperand(offset, Code::kFlagsOffset));
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ and_(offset, ~Code::kFlagsNotUsedInLookup);
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(offset, flags);
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ j(not_equal, &miss);
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Restore offset and re-load code entry from cache.
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ pop(offset);
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(offset, Operand::StaticArray(offset, times_2, value_offset));
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Jump to the first instruction in the code stub.
95592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ add(offset, Immediate(Code::kHeaderSize - kHeapObjectTag));
96592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ jmp(offset);
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Pop at miss.
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&miss);
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ pop(offset);
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1058defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Helper function used to check that the dictionary doesn't contain
1068defd9ff6930b4e24729971a61cf7469daf119beSteve Block// the property. This function may return false negatives, so miss_label
1078defd9ff6930b4e24729971a61cf7469daf119beSteve Block// must always call a backup property check that is complete.
1088defd9ff6930b4e24729971a61cf7469daf119beSteve Block// This function is safe to call if the receiver has fast properties.
1098defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Name must be a symbol and receiver must be a heap object.
110592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochstatic void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
111592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                             Label* miss_label,
112592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                             Register receiver,
113592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                             Handle<String> name,
114592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                             Register r0,
115592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                             Register r1) {
1168defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ASSERT(name->IsSymbol());
11744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm->isolate()->counters();
11844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->negative_lookups(), 1);
11944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->negative_lookups_miss(), 1);
1208defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1218defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset));
1228defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1238defd9ff6930b4e24729971a61cf7469daf119beSteve Block  const int kInterceptorOrAccessCheckNeededMask =
1248defd9ff6930b4e24729971a61cf7469daf119beSteve Block      (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
1253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1268defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Bail out if the receiver has a named interceptor or requires access checks.
1273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ test_b(FieldOperand(r0, Map::kBitFieldOffset),
1283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch            kInterceptorOrAccessCheckNeededMask);
129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_zero, miss_label);
1308defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Check that receiver is a JSObject.
1323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CmpInstanceType(r0, FIRST_SPEC_OBJECT_TYPE);
133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(below, miss_label);
1348defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1358defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Load properties array.
1368defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Register properties = r0;
1378defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset));
1388defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1398defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Check that the properties array is a dictionary.
1408defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ cmp(FieldOperand(properties, HeapObject::kMapOffset),
14144f0eee88ff00398ff7f715fab053374d808c90dSteve Block         Immediate(masm->isolate()->factory()->hash_table_map()));
1428defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ j(not_equal, miss_label);
1438defd9ff6930b4e24729971a61cf7469daf119beSteve Block
144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
145592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  StringDictionaryLookupStub::GenerateNegativeLookup(masm,
146592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                     miss_label,
147592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                     &done,
148592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                     properties,
149592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                     name,
150592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                     r1);
1518defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ bind(&done);
15244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->negative_lookups_miss(), 1);
1538defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
1548defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1558defd9ff6930b4e24729971a61cf7469daf119beSteve Block
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCache::GenerateProbe(MacroAssembler* masm,
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Code::Flags flags,
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Register receiver,
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Register name,
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Register scratch,
1613e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                              Register extra,
1623e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                              Register extra2) {
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
165592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Assert that code is valid.  The shifting code relies on the entry size
166592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // being 8.
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(sizeof(Entry) == 8);
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
169592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Assert the flags do not name a specific type.
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
172592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Assert that there are no register conflicts.
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!scratch.is(receiver));
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!scratch.is(name));
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!extra.is(receiver));
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!extra.is(name));
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!extra.is(scratch));
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
179592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Assert scratch and extra registers are valid, and extra2 is unused.
1803e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(!scratch.is(no_reg));
1813e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(extra2.is(no_reg));
1823e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
1843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver, &miss);
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the map of the receiver and compute the hash.
187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ mov(scratch, FieldOperand(name, String::kHashFieldOffset));
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ xor_(scratch, flags);
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize);
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Probe the primary table.
193592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  ProbeTable(isolate(), masm, flags, kPrimary, name, scratch, extra);
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Primary miss: Compute hash for secondary probe.
196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ mov(scratch, FieldOperand(name, String::kHashFieldOffset));
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ xor_(scratch, flags);
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize);
200592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ sub(scratch, name);
201592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ add(scratch, Immediate(flags));
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(scratch, (kSecondaryTableSize - 1) << kHeapObjectTagSize);
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Probe the secondary table.
205592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  ProbeTable(isolate(), masm, flags, kSecondary, name, scratch, extra);
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Cache miss: Fall-through and let caller handle the miss by
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // entering the runtime system.
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                       int index,
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                       Register prototype) {
21680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ LoadGlobalFunction(index, prototype);
21780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ LoadGlobalFunctionInitialMap(prototype, prototype);
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the prototype from the initial map.
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
224592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    MacroAssembler* masm,
225592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    int index,
226592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Register prototype,
227592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Label* miss) {
2280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Check we're still in the same context.
2290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ cmp(Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)),
23044f0eee88ff00398ff7f715fab053374d808c90dSteve Block         masm->isolate()->global());
2310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ j(not_equal, miss);
2327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Get the global function with the given index.
233592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Handle<JSFunction> function(
234592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      JSFunction::cast(masm->isolate()->global_context()->get(index)));
2357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Load its initial map. The global functions all have initial maps.
2367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ Set(prototype, Immediate(Handle<Map>(function->initial_map())));
2377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Load the prototype from the initial map.
2387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
2397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register receiver,
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register scratch,
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Label* miss_label) {
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
2473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver, miss_label);
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object is a JS array.
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, miss_label);
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load length directly from the JS array.
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset));
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate code to check if an object is a string.  If the object is
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// a string, the map's instance type is left in the scratch register.
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GenerateStringCheck(MacroAssembler* masm,
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Register receiver,
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Register scratch,
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Label* smi,
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Label* non_string_object) {
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object isn't a smi.
2673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver, smi);
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object is a string.
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
27269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kNotStringTag != 0);
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ test(scratch, Immediate(kNotStringTag));
274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_zero, non_string_object);
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Register receiver,
280402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                            Register scratch1,
281402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                            Register scratch2,
2821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                            Label* miss,
2831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                            bool support_wrappers) {
284402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Label check_wrapper;
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if the object is a string leaving the instance type in the
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch register.
2881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  GenerateStringCheck(masm, receiver, scratch1, miss,
2891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      support_wrappers ? &check_wrapper : miss);
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
291d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Load length from the string and convert to a smi.
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(eax, FieldOperand(receiver, String::kLengthOffset));
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (support_wrappers) {
2961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Check if the object is a JSValue wrapper.
2971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ bind(&check_wrapper);
2981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ cmp(scratch1, JS_VALUE_TYPE);
299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(not_equal, miss);
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Check if the wrapped value is a string and load the length
3021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // directly if it is.
3031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset));
3041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    GenerateStringCheck(masm, scratch2, scratch1, miss, miss);
3051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ mov(eax, FieldOperand(scratch2, String::kLengthOffset));
3061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ ret(0);
3071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 Register receiver,
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 Register scratch1,
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 Register scratch2,
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 Label* miss_label) {
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
317592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ mov(eax, scratch1);
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Load a fast property out of a holder object (src). In-object properties
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// are loaded directly otherwise the property is loaded from the properties
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// fixed array.
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
326592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                            Register dst,
327592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                            Register src,
328592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                            Handle<JSObject> holder,
329592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                            int index) {
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adjust for the number of properties stored in the holder.
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  index -= holder->map()->inobject_properties();
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (index < 0) {
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Get the property straight out of the holder.
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = holder->map()->instance_size() + (index * kPointerSize);
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(dst, FieldOperand(src, offset));
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Calculate the offset into the properties array.
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = index * kPointerSize + FixedArray::kHeaderSize;
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset));
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(dst, FieldOperand(dst, offset));
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
345402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescustatic void PushInterceptorArguments(MacroAssembler* masm,
346402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                     Register receiver,
347402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                     Register holder,
348402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                     Register name,
349592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                     Handle<JSObject> holder_obj) {
350402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(name);
351592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor());
352592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor));
3536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register scratch = name;
354592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ mov(scratch, Immediate(interceptor));
3556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(scratch);
356402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(receiver);
3576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(holder);
3586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(FieldOperand(scratch, InterceptorInfo::kDataOffset));
359402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
360402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
361402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
362592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochstatic void CompileCallLoadPropertyWithInterceptor(
363592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    MacroAssembler* masm,
364592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Register receiver,
365592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Register holder,
366592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Register name,
367592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSObject> holder_obj) {
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
369402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ CallExternalReference(
37044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly),
37144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        masm->isolate()),
37244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      5);
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37690bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner// Number of pointers to be reserved on stack for fast API call.
37790bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brennerstatic const int kFastApiCallArguments = 3;
37890bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner
37990bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner
3808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang// Reserves space for the extra arguments to API function in the
381402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// caller's frame.
382402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu//
383402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// These arguments are set by CheckPrototypes and GenerateFastApiCall.
384402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescustatic void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
385402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // ----------- S t a t e -------------
386402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- esp[0] : return address
387402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- esp[4] : last argument in the internal frame of the caller
388402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // -----------------------------------
389402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ pop(scratch);
39090bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  for (int i = 0; i < kFastApiCallArguments; i++) {
39190bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner    __ push(Immediate(Smi::FromInt(0)));
39290bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  }
393402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(scratch);
394402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
395402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
396402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
397402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// Undoes the effects of ReserveSpaceForFastApiCall.
398402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescustatic void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
399402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // ----------- S t a t e -------------
40090bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  //  -- esp[0]  : return address.
40190bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  //  -- esp[4]  : last fast api call extra argument.
402402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- ...
40390bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  //  -- esp[kFastApiCallArguments * 4] : first fast api call extra argument.
40490bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  //  -- esp[kFastApiCallArguments * 4 + 4] : last argument in the internal
40590bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  //                                          frame.
406402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // -----------------------------------
407402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ pop(scratch);
408592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ add(esp, Immediate(kPointerSize * kFastApiCallArguments));
409402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(scratch);
410402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
411402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
412402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
4138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang// Generates call to API function.
414592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochstatic void GenerateFastApiCall(MacroAssembler* masm,
415592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                const CallOptimization& optimization,
416592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                int argc) {
417402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // ----------- S t a t e -------------
418402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- esp[0]              : return address
419402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- esp[4]              : object passing the type check
420402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //                           (last fast api call extra argument,
421402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //                            set by CheckPrototypes)
42290bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  //  -- esp[8]              : api function
423402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //                           (first fast api call extra argument)
42490bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  //  -- esp[12]             : api call data
42590bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  //  -- esp[16]             : last argument
426402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- ...
42790bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  //  -- esp[(argc + 3) * 4] : first argument
42890bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  //  -- esp[(argc + 4) * 4] : receiver
429402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // -----------------------------------
430402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Get the function and setup the context.
431592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Handle<JSFunction> function = optimization.constant_function();
432592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ mov(edi, Immediate(function));
433402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
434402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
4358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Pass the additional arguments.
43690bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  __ mov(Operand(esp, 2 * kPointerSize), edi);
437592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
438592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Handle<Object> call_data(api_call_info->data());
439592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (masm->isolate()->heap()->InNewSpace(*call_data)) {
440592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(ecx, api_call_info);
441402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset));
44290bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner    __ mov(Operand(esp, 3 * kPointerSize), ebx);
443402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  } else {
444592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(Operand(esp, 3 * kPointerSize), Immediate(call_data));
445402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
446402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
4478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Prepare arguments.
44890bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  __ lea(eax, Operand(esp, 3 * kPointerSize));
449402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
4508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const int kApiArgc = 1;  // API function gets reference to the v8::Arguments.
45190bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner
4528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Allocate the v8::Arguments structure in the arguments' space since
4538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // it's not controlled by GC.
4548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const int kApiStackSpace = 4;
4558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
4563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ PrepareCallApiFunction(kApiArgc + kApiStackSpace);
4578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
4588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(ApiParameterOperand(1), eax);  // v8::Arguments::implicit_args_.
459592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ add(eax, Immediate(argc * kPointerSize));
4608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(ApiParameterOperand(2), eax);  // v8::Arguments::values_.
4618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Set(ApiParameterOperand(3), Immediate(argc));  // v8::Arguments::length_.
4628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // v8::Arguments::is_construct_call_.
4638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Set(ApiParameterOperand(4), Immediate(0));
4648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
4658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // v8::InvocationCallback's argument.
4668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ lea(eax, ApiParameterOperand(1));
4678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(ApiParameterOperand(0), eax);
46890bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner
469592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Function address is a foreign pointer outside V8's heap.
470592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Address function_address = v8::ToCData<Address>(api_call_info->callback());
471592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ CallApiFunctionAndReturn(function_address,
472592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                              argc + kFastApiCallArguments + 1);
473402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
474402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
475402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CallInterceptorCompiler BASE_EMBEDDED {
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
478402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CallInterceptorCompiler(StubCompiler* stub_compiler,
479402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                          const ParameterCount& arguments,
480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          Register name,
481592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                          Code::ExtraICState extra_state)
482402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      : stub_compiler_(stub_compiler),
483402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        arguments_(arguments),
484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        name_(name),
485592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        extra_state_(extra_state) {}
486592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
487592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  void Compile(MacroAssembler* masm,
488592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch               Handle<JSObject> object,
489592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch               Handle<JSObject> holder,
490592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch               Handle<String> name,
491592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch               LookupResult* lookup,
492592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch               Register receiver,
493592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch               Register scratch1,
494592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch               Register scratch2,
495592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch               Register scratch3,
496592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch               Label* miss) {
497402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    ASSERT(holder->HasNamedInterceptor());
498402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
499402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
500402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Check that the receiver isn't a smi.
5013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(receiver, miss);
502402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
503402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    CallOptimization optimization(lookup);
5046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (optimization.is_constant_call()) {
505592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3,
506592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                       holder, lookup, name, optimization, miss);
507402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    } else {
508592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3,
509592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                     name, holder, miss);
510402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    }
511402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
513402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu private:
514592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  void CompileCacheable(MacroAssembler* masm,
515592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                        Handle<JSObject> object,
516592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                        Register receiver,
517592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                        Register scratch1,
518592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                        Register scratch2,
519592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                        Register scratch3,
520592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                        Handle<JSObject> interceptor_holder,
521592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                        LookupResult* lookup,
522592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                        Handle<String> name,
523592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                        const CallOptimization& optimization,
524592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                        Label* miss_label) {
525402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    ASSERT(optimization.is_constant_call());
526402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    ASSERT(!lookup->holder()->IsGlobalObject());
527402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
528402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    int depth1 = kInvalidProtoDepth;
529402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    int depth2 = kInvalidProtoDepth;
530402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    bool can_do_fast_api_call = false;
531402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    if (optimization.is_simple_api_call() &&
532402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        !lookup->holder()->IsGlobalObject()) {
533592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      depth1 = optimization.GetPrototypeDepthOfExpectedType(
534592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          object, interceptor_holder);
535402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      if (depth1 == kInvalidProtoDepth) {
536592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        depth2 = optimization.GetPrototypeDepthOfExpectedType(
537592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch            interceptor_holder, Handle<JSObject>(lookup->holder()));
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
539592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      can_do_fast_api_call =
540592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth;
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
54344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Counters* counters = masm->isolate()->counters();
54444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ IncrementCounter(counters->call_const_interceptor(), 1);
545402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
546402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    if (can_do_fast_api_call) {
54744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1);
548402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      ReserveSpaceForFastApiCall(masm, scratch1);
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Check that the maps from receiver to interceptor's holder
552f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // haven't changed and thus we can invoke interceptor.
553402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Label miss_cleanup;
554402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
555402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Register holder =
556592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
557592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                        scratch1, scratch2, scratch3,
558592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                        name, depth1, miss);
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Invoke an interceptor and if it provides a value,
561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // branch to |regular_invoke|.
562402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Label regular_invoke;
563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    LoadWithInterceptor(masm, receiver, holder, interceptor_holder,
564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                        &regular_invoke);
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Interceptor returned nothing for this property.  Try to use cached
567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // constant function.
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Check that the maps from interceptor's holder to constant function's
570f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // holder haven't changed and thus we can use cached constant function.
571592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (*interceptor_holder != lookup->holder()) {
5727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      stub_compiler_->CheckPrototypes(interceptor_holder, receiver,
573592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                      Handle<JSObject>(lookup->holder()),
574592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                      scratch1, scratch2, scratch3,
575592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                      name, depth2, miss);
5767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    } else {
5777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // CheckPrototypes has a side effect of fetching a 'holder'
5787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // for API (object which is instanceof for the signature).  It's
5797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // safe to omit it here, as if present, it should be fetched
5807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // by the previous CheckPrototypes.
5817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ASSERT(depth2 == kInvalidProtoDepth);
5827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
584f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Invoke function.
585402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    if (can_do_fast_api_call) {
586592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      GenerateFastApiCall(masm, optimization, arguments_.immediate());
587402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    } else {
588592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          ? CALL_AS_FUNCTION
590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          : CALL_AS_METHOD;
591402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ InvokeFunction(optimization.constant_function(), arguments_,
592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        JUMP_FUNCTION, NullCallWrapper(), call_kind);
593402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    }
594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Deferred code for fast API call case---clean preallocated space.
596402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    if (can_do_fast_api_call) {
597402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ bind(&miss_cleanup);
598402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      FreeSpaceForFastApiCall(masm, scratch1);
599402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ jmp(miss_label);
600402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    }
601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
602f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Invoke a regular function.
603402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ bind(&regular_invoke);
604402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    if (can_do_fast_api_call) {
605402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      FreeSpaceForFastApiCall(masm, scratch1);
606402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    }
607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void CompileRegular(MacroAssembler* masm,
610592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                      Handle<JSObject> object,
611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register receiver,
612402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                      Register scratch1,
613402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                      Register scratch2,
6143bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                      Register scratch3,
615592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                      Handle<String> name,
616592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                      Handle<JSObject> interceptor_holder,
617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Label* miss_label) {
618402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Register holder =
619f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
620592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                        scratch1, scratch2, scratch3,
621592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                        name, miss_label);
622402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
623592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
624e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Save the name_ register across the call.
625e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(name_);
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
627592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder);
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
629402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ CallExternalReference(
63044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall),
63144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          masm->isolate()),
63244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        5);
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
634e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Restore the name_ register.
635e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ pop(name_);
636592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
637592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Leave the internal frame.
638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
640402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void LoadWithInterceptor(MacroAssembler* masm,
641402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                           Register receiver,
642402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                           Register holder,
643592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                           Handle<JSObject> holder_obj,
644402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                           Label* interceptor_succeeded) {
645592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    {
646592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      FrameScope scope(masm, StackFrame::INTERNAL);
647592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ push(holder);  // Save the holder.
648592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ push(name_);  // Save the name.
649592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
650592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      CompileCallLoadPropertyWithInterceptor(masm,
651592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                             receiver,
652592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                             holder,
653592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                             name_,
654592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                             holder_obj);
655592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
656592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ pop(name_);  // Restore the name.
657592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ pop(receiver);  // Restore the holder.
658592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Leave the internal frame.
659592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
660402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
66144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmp(eax, masm->isolate()->factory()->no_interceptor_result_sentinel());
662402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ j(not_equal, interceptor_succeeded);
663402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
664402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
665402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  StubCompiler* stub_compiler_;
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const ParameterCount& arguments_;
667e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Register name_;
668592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Code::ExtraICState extra_state_;
669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
674592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Handle<Code> code = (kind == Code::LOAD_IC)
675592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ? masm->isolate()->builtins()->LoadIC_Miss()
676592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      : masm->isolate()->builtins()->KeyedLoadIC_Miss();
677592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ jmp(code, RelocInfo::CODE_TARGET);
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) {
682592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Handle<Code> code =
683592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
684592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ jmp(code, RelocInfo::CODE_TARGET);
685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
688402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// Both name_reg and receiver_reg are preserved on jumps to miss_label,
689402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// but may be destroyed if store is successful.
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateStoreField(MacroAssembler* masm,
691592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                      Handle<JSObject> object,
692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      int index,
693592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                      Handle<Map> transition,
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register receiver_reg,
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register name_reg,
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register scratch,
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Label* miss_label) {
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object isn't a smi.
6993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver_reg, miss_label);
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the object hasn't changed.
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset),
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         Immediate(Handle<Map>(object->map())));
704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, miss_label);
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform global security token check if needed.
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsJSGlobalProxy()) {
708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub never generated for non-global objects that require access
712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // checks.
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform map transition for the receiver if necessary.
716592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) {
717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The properties must be extended before we can store the value.
718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // We jump to a runtime call that extends the properties array.
719402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ pop(scratch);  // Return address.
720402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ push(receiver_reg);
721592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(Immediate(transition));
722402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ push(eax);
723402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ push(scratch);
7246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ TailCallExternalReference(
72544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
72644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          masm->isolate()),
72744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        3,
72844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        1);
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
732592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (!transition.is_null()) {
733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Update the map of the object; no write barrier updating is
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // needed because the map is never in new space.
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset),
736592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch           Immediate(transition));
737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adjust for the number of properties stored in the object. Even in the
740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // face of a transition we can use the old map here because the size of the
741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object and the number of in-object properties is not going to change.
742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  index -= object->map()->inobject_properties();
743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (index < 0) {
745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Set the property straight into the object.
746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = object->map()->instance_size() + (index * kPointerSize);
747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(FieldOperand(receiver_reg, offset), eax);
748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Update the write barrier for the array address.
750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Pass the value being stored in the now unused name_reg.
751592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(name_reg, eax);
752592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ RecordWriteField(receiver_reg,
753592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                        offset,
754592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                        name_reg,
755592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                        scratch,
756592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                        kDontSaveFPRegs);
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Write to the properties array.
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = index * kPointerSize + FixedArray::kHeaderSize;
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Get the properties array (optimistically).
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(FieldOperand(scratch, offset), eax);
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Update the write barrier for the array address.
765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Pass the value being stored in the now unused name_reg.
766592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(name_reg, eax);
767592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ RecordWriteField(scratch,
768592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                        offset,
769592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                        name_reg,
770592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                        receiver_reg,
771592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                        kDontSaveFPRegs);
772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the value (register eax).
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Generate code to check that a global property cell is empty. Create
7806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// the property cell at compilation time if no cell exists for the
7816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// property.
782592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochstatic void GenerateCheckPropertyCell(MacroAssembler* masm,
783592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                      Handle<GlobalObject> global,
784592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                      Handle<String> name,
785592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                      Register scratch,
786592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                      Label* miss) {
787592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Handle<JSGlobalPropertyCell> cell =
788592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      GlobalObject::EnsurePropertyCell(global, name);
7896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(cell->value()->IsTheHole());
790592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Handle<Oddball> the_hole = masm->isolate()->factory()->the_hole_value();
791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (Serializer::enabled()) {
792592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(scratch, Immediate(cell));
793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset),
794592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch           Immediate(the_hole));
795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
796592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ cmp(Operand::Cell(cell), Immediate(the_hole));
797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, miss);
7996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
8006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8028defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Calls GenerateCheckPropertyCell for each global object in the prototype chain
8038defd9ff6930b4e24729971a61cf7469daf119beSteve Block// from object to (but not including) holder.
804592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochstatic void GenerateCheckPropertyCells(MacroAssembler* masm,
805592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                       Handle<JSObject> object,
806592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                       Handle<JSObject> holder,
807592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                       Handle<String> name,
808592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                       Register scratch,
809592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                       Label* miss) {
810592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Handle<JSObject> current = object;
811592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  while (!current.is_identical_to(holder)) {
8128defd9ff6930b4e24729971a61cf7469daf119beSteve Block    if (current->IsGlobalObject()) {
813592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      GenerateCheckPropertyCell(masm,
814592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                Handle<GlobalObject>::cast(current),
815592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                name,
816592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                scratch,
817592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                miss);
8188defd9ff6930b4e24729971a61cf7469daf119beSteve Block    }
819592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    current = Handle<JSObject>(JSObject::cast(current->GetPrototype()));
8208defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
8218defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
8228defd9ff6930b4e24729971a61cf7469daf119beSteve Block
823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __
824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm())
825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
827592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochRegister StubCompiler::CheckPrototypes(Handle<JSObject> object,
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       Register object_reg,
829592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                       Handle<JSObject> holder,
830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       Register holder_reg,
8313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       Register scratch1,
8323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       Register scratch2,
833592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                       Handle<String> name,
8348defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                       int save_at_depth,
8353bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       Label* miss) {
8368defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Make sure there's no overlap between holder and object registers.
8373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
8383bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
8393bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch         && !scratch2.is(scratch1));
84044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
8418defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Keep track of the current object in register reg.
8428defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Register reg = object_reg;
843592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Handle<JSObject> current = object;
8448defd9ff6930b4e24729971a61cf7469daf119beSteve Block  int depth = 0;
8458defd9ff6930b4e24729971a61cf7469daf119beSteve Block
8468defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (save_at_depth == depth) {
8478defd9ff6930b4e24729971a61cf7469daf119beSteve Block    __ mov(Operand(esp, kPointerSize), reg);
8488defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8508defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Traverse the prototype chain and check the maps in the prototype chain for
8518defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // fast and global objects or do negative lookup for normal objects.
852592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  while (!current.is_identical_to(holder)) {
853592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    ++depth;
8548defd9ff6930b4e24729971a61cf7469daf119beSteve Block
8558defd9ff6930b4e24729971a61cf7469daf119beSteve Block    // Only global objects and objects that do not require access
8568defd9ff6930b4e24729971a61cf7469daf119beSteve Block    // checks are allowed in stubs.
8578defd9ff6930b4e24729971a61cf7469daf119beSteve Block    ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
8588defd9ff6930b4e24729971a61cf7469daf119beSteve Block
859592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSObject> prototype(JSObject::cast(current->GetPrototype()));
8608defd9ff6930b4e24729971a61cf7469daf119beSteve Block    if (!current->HasFastProperties() &&
8618defd9ff6930b4e24729971a61cf7469daf119beSteve Block        !current->IsJSGlobalObject() &&
8628defd9ff6930b4e24729971a61cf7469daf119beSteve Block        !current->IsJSGlobalProxy()) {
8638defd9ff6930b4e24729971a61cf7469daf119beSteve Block      if (!name->IsSymbol()) {
864592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        name = factory()->LookupSymbol(name);
8658defd9ff6930b4e24729971a61cf7469daf119beSteve Block      }
866592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ASSERT(current->property_dictionary()->FindEntry(*name) ==
8678defd9ff6930b4e24729971a61cf7469daf119beSteve Block             StringDictionary::kNotFound);
8688defd9ff6930b4e24729971a61cf7469daf119beSteve Block
869592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      GenerateDictionaryNegativeLookup(masm(), miss, reg, name,
870592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                       scratch1, scratch2);
871257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
8723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
873592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      reg = holder_reg;  // From now on the object will be in holder_reg.
8743bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
875592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    } else {
876592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      bool in_new_space = heap()->InNewSpace(*prototype);
877592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      Handle<Map> current_map(current->map());
878592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (in_new_space) {
879592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        // Save the map in scratch1 for later.
8803bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
881592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ cmp(scratch1, Immediate(current_map));
882592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      } else {
883592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
884592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch               Immediate(current_map));
8858defd9ff6930b4e24729971a61cf7469daf119beSteve Block      }
8868defd9ff6930b4e24729971a61cf7469daf119beSteve Block      // Branch on the result of the map check.
887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ j(not_equal, miss);
888592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Check access rights to the global object.  This has to happen after
889592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // the map check so that we know that the object is actually a global
890592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // object.
8918defd9ff6930b4e24729971a61cf7469daf119beSteve Block      if (current->IsJSGlobalProxy()) {
892592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ CheckAccessGlobalProxy(reg, scratch2, miss);
893592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      }
894592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      reg = holder_reg;  // From now on the object will be in holder_reg.
895592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
896592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (in_new_space) {
897592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        // The prototype is in new space; we cannot store a reference to it
898592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        // in the code.  Load it from the map.
899592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
900592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      } else {
901592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        // The prototype is in old space; load it directly.
902592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ mov(reg, prototype);
903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
9058defd9ff6930b4e24729971a61cf7469daf119beSteve Block
9068defd9ff6930b4e24729971a61cf7469daf119beSteve Block    if (save_at_depth == depth) {
9078defd9ff6930b4e24729971a61cf7469daf119beSteve Block      __ mov(Operand(esp, kPointerSize), reg);
9088defd9ff6930b4e24729971a61cf7469daf119beSteve Block    }
9098defd9ff6930b4e24729971a61cf7469daf119beSteve Block
9108defd9ff6930b4e24729971a61cf7469daf119beSteve Block    // Go to the next object in the prototype chain.
9118defd9ff6930b4e24729971a61cf7469daf119beSteve Block    current = prototype;
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
913592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  ASSERT(current.is_identical_to(holder));
9148defd9ff6930b4e24729971a61cf7469daf119beSteve Block
9158defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Log the check depth.
91644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
9178defd9ff6930b4e24729971a61cf7469daf119beSteve Block
9188defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Check the holder map.
9198defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
9208defd9ff6930b4e24729971a61cf7469daf119beSteve Block         Immediate(Handle<Map>(holder->map())));
921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, miss);
9228defd9ff6930b4e24729971a61cf7469daf119beSteve Block
9238defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Perform security check for access to the global object.
9248defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
9258defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (holder->IsJSGlobalProxy()) {
9263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    __ CheckAccessGlobalProxy(reg, scratch1, miss);
927592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
928592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
929592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // If we've skipped any global objects, it's not enough to verify that
930592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // their maps haven't changed.  We also need to check that the property
931592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // cell for the property is still empty.
932592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss);
933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
934402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Return the register containing the holder.
9358defd9ff6930b4e24729971a61cf7469daf119beSteve Block  return reg;
936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
939592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid StubCompiler::GenerateLoadField(Handle<JSObject> object,
940592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                     Handle<JSObject> holder,
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Register receiver,
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Register scratch1,
943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Register scratch2,
9443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                     Register scratch3,
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     int index,
946592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                     Handle<String> name,
947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Label* miss) {
948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
9493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver, miss);
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the prototype chain.
952592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Register reg = CheckPrototypes(
953592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the value from the properties.
956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateFastPropertyLoad(masm(), eax, reg, holder, index);
957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
961592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid StubCompiler::GenerateLoadCallback(Handle<JSObject> object,
962592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                        Handle<JSObject> holder,
963592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                        Register receiver,
964592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                        Register name_reg,
965592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                        Register scratch1,
966592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                        Register scratch2,
967592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                        Register scratch3,
968592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                        Handle<AccessorInfo> callback,
969592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                        Handle<String> name,
970592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                        Label* miss) {
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
9723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver, miss);
973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the maps haven't changed.
975592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Register reg = CheckPrototypes(object, receiver, holder, scratch1,
976592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                 scratch2, scratch3, name, miss);
977d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
9788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Insert additional parameters into the stack frame above return address.
9798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ASSERT(!scratch3.is(reg));
9808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ pop(scratch3);  // Get return address to place it below.
9818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(receiver);  // receiver
983592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ mov(scratch2, esp);
9848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ASSERT(!scratch2.is(reg));
985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(reg);  // holder
9869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Push data from AccessorInfo.
987592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (isolate()->heap()->InNewSpace(callback->data())) {
988592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(scratch1, Immediate(callback));
9898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset));
9909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  } else {
991592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(Immediate(Handle<Object>(callback->data())));
9929dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
9938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
994d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Save a pointer to where we pushed the arguments pointer.
9956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // This will be passed as the const AccessorInfo& to the C++ callback.
9968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ push(scratch2);
9978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
9988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ push(name_reg);  // name
9998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(ebx, esp);  // esp points to reference to name (handler).
10008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
10018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ push(scratch3);  // Restore return address.
1002d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
10038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // 3 elements array for v8::Agruments::values_, handler for name and pointer
10048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // to the values (it considered as smi in GC).
10058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const int kStackSpace = 5;
10068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const int kApiArgc = 2;
10078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
10083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ PrepareCallApiFunction(kApiArgc);
10098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(ApiParameterOperand(0), ebx);  // name.
1010592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ add(ebx, Immediate(kPointerSize));
10118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(ApiParameterOperand(1), ebx);  // arguments pointer.
10128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1013e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emitting a stub call may try to allocate (if the code is not
1014e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // already generated).  Do not allow the assembler to perform a
1015e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // garbage collection but instead return the allocation failure
1016e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // object.
1017592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Address getter_address = v8::ToCData<Address>(callback->getter());
1018592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ CallApiFunctionAndReturn(getter_address, kStackSpace);
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1022592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid StubCompiler::GenerateLoadConstant(Handle<JSObject> object,
1023592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                        Handle<JSObject> holder,
1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register receiver,
1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch1,
1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch2,
10273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                        Register scratch3,
1028592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                        Handle<Object> value,
1029592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                        Handle<String> name,
1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Label* miss) {
1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
10323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver, miss);
1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the maps haven't changed.
1035592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  CheckPrototypes(
1036592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the constant value.
1039592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ mov(eax, value);
1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1044592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object,
1045592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                           Handle<JSObject> interceptor_holder,
1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           LookupResult* lookup,
1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register receiver,
1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register name_reg,
1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register scratch1,
1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register scratch2,
10513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                           Register scratch3,
1052592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                           Handle<String> name,
1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Label* miss) {
10547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(interceptor_holder->HasNamedInterceptor());
10557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
10567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
10577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Check that the receiver isn't a smi.
10583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver, miss);
10597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
10607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // So far the most popular follow ups for interceptor loads are FIELD
10617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // and CALLBACKS, so inline only them, other cases may be added
10627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // later.
10637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  bool compile_followup_inline = false;
10647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (lookup->IsProperty() && lookup->IsCacheable()) {
10657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    if (lookup->type() == FIELD) {
10667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      compile_followup_inline = true;
10677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    } else if (lookup->type() == CALLBACKS &&
1068592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch               lookup->GetCallbackObject()->IsAccessorInfo()) {
1069592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      compile_followup_inline =
1070592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL;
10717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
10727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
10737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
10747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (compile_followup_inline) {
10757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Compile the interceptor call, followed by inline code to load the
10767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // property from further up the prototype chain if the call fails.
10777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Check that the maps haven't changed.
10787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
10793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                          scratch1, scratch2, scratch3,
10803bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                          name, miss);
10817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1));
10827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
10837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Save necessary data before invoking an interceptor.
10847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Requires a frame to make GC aware of pushed pointers.
1085592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    {
1086592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      FrameScope frame_scope(masm(), StackFrame::INTERNAL);
10877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1088592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
1089592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        // CALLBACKS case needs a receiver to be passed into C++ callback.
1090592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ push(receiver);
1091592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      }
1092592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ push(holder_reg);
1093592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ push(name_reg);
10947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1095592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Invoke an interceptor.  Note: map checks from receiver to
1096592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // interceptor's holder has been compiled before (see a caller
1097592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // of this method.)
1098592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      CompileCallLoadPropertyWithInterceptor(masm(),
1099592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                             receiver,
1100592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                             holder_reg,
1101592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                             name_reg,
1102592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                             interceptor_holder);
1103592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1104592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Check if interceptor provided a value for property.  If it's
1105592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // the case, return immediately.
1106592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      Label interceptor_failed;
1107592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ cmp(eax, factory()->no_interceptor_result_sentinel());
1108592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ j(equal, &interceptor_failed);
1109592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      frame_scope.GenerateLeaveFrame();
1110592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ ret(0);
11117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1112592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ bind(&interceptor_failed);
1113592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ pop(name_reg);
1114592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ pop(holder_reg);
1115592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
1116592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ pop(receiver);
1117592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      }
1118592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1119592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Leave the internal frame.
1120592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
11217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Check that the maps from interceptor's holder to lookup's holder
11237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // haven't changed.  And load lookup's holder into holder_reg.
1124592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (*interceptor_holder != lookup->holder()) {
11257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      holder_reg = CheckPrototypes(interceptor_holder,
11267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   holder_reg,
1127592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                   Handle<JSObject>(lookup->holder()),
11287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   scratch1,
11297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   scratch2,
11303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                   scratch3,
11317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   name,
11327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   miss);
11337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
11347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    if (lookup->type() == FIELD) {
11367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // We found FIELD property in prototype chain of interceptor's holder.
11377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Retrieve a field from field's holder.
11387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      GenerateFastPropertyLoad(masm(), eax, holder_reg,
1139592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                               Handle<JSObject>(lookup->holder()),
1140592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                               lookup->GetFieldIndex());
11417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ ret(0);
11427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    } else {
11437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // We found CALLBACKS property in prototype chain of interceptor's
11447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // holder.
11457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ASSERT(lookup->type() == CALLBACKS);
1146592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      Handle<AccessorInfo> callback(
1147592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          AccessorInfo::cast(lookup->GetCallbackObject()));
11487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ASSERT(callback->getter() != NULL);
11497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Tail call to runtime.
11517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Important invariant in CALLBACKS case: the code above must be
11527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // structured to never clobber |receiver| register.
11537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ pop(scratch2);  // return address
11547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(receiver);
11557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(holder_reg);
1156592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ mov(holder_reg, Immediate(callback));
11577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset));
11588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ push(holder_reg);
11597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(name_reg);
11607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(scratch2);  // restore return address
11617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ExternalReference ref =
116344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ExternalReference(IC_Utility(IC::kLoadCallbackProperty),
116444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            masm()->isolate());
11657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ TailCallExternalReference(ref, 5, 1);
11667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
11677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  } else {  // !compile_followup_inline
11687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Call the runtime system to load the interceptor.
11697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Check that the maps haven't changed.
11707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    Register holder_reg =
11717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        CheckPrototypes(object, receiver, interceptor_holder,
11723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                        scratch1, scratch2, scratch3, name, miss);
11737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ pop(scratch2);  // save old return address
11747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    PushInterceptorArguments(masm(), receiver, holder_reg,
11757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                             name_reg, interceptor_holder);
11767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ push(scratch2);  // restore old return address
11777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
117844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ExternalReference ref =
117944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad),
118044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          isolate());
11817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ TailCallExternalReference(ref, 5, 1);
11827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1186592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) {
11877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (kind_ == Code::KEYED_CALL_IC) {
1188592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ cmp(ecx, Immediate(name));
1189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(not_equal, miss);
11907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
11917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
11927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1194592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
1195592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                   Handle<JSObject> holder,
1196592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                   Handle<String> name,
119759151504615d929945dc59db37bf1166937748c6Steve Block                                                   Label* miss) {
119859151504615d929945dc59db37bf1166937748c6Steve Block  ASSERT(holder->IsGlobalObject());
119959151504615d929945dc59db37bf1166937748c6Steve Block
120059151504615d929945dc59db37bf1166937748c6Steve Block  // Get the number of arguments.
120159151504615d929945dc59db37bf1166937748c6Steve Block  const int argc = arguments().immediate();
120259151504615d929945dc59db37bf1166937748c6Steve Block
120359151504615d929945dc59db37bf1166937748c6Steve Block  // Get the receiver from the stack.
120459151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
120559151504615d929945dc59db37bf1166937748c6Steve Block
120659151504615d929945dc59db37bf1166937748c6Steve Block  // If the object is the holder then we know that it's a global
120759151504615d929945dc59db37bf1166937748c6Steve Block  // object which can only happen for contextual calls. In this case,
120859151504615d929945dc59db37bf1166937748c6Steve Block  // the receiver cannot be a smi.
1209592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (!object.is_identical_to(holder)) {
12103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(edx, miss);
121159151504615d929945dc59db37bf1166937748c6Steve Block  }
121259151504615d929945dc59db37bf1166937748c6Steve Block
121359151504615d929945dc59db37bf1166937748c6Steve Block  // Check that the maps haven't changed.
121459151504615d929945dc59db37bf1166937748c6Steve Block  CheckPrototypes(object, edx, holder, ebx, eax, edi, name, miss);
121559151504615d929945dc59db37bf1166937748c6Steve Block}
121659151504615d929945dc59db37bf1166937748c6Steve Block
121759151504615d929945dc59db37bf1166937748c6Steve Block
1218592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid CallStubCompiler::GenerateLoadFunctionFromCell(
1219592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSGlobalPropertyCell> cell,
1220592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSFunction> function,
1221592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Label* miss) {
122259151504615d929945dc59db37bf1166937748c6Steve Block  // Get the value from the cell.
1223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (Serializer::enabled()) {
1224592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(edi, Immediate(cell));
1225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset));
1226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
1227592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(edi, Operand::Cell(cell));
1228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
122959151504615d929945dc59db37bf1166937748c6Steve Block
123059151504615d929945dc59db37bf1166937748c6Steve Block  // Check that the cell contains the same function.
1231592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (isolate()->heap()->InNewSpace(*function)) {
123259151504615d929945dc59db37bf1166937748c6Steve Block    // We can't embed a pointer to a function in new space so we have
123359151504615d929945dc59db37bf1166937748c6Steve Block    // to verify that the shared function info is unchanged. This has
123459151504615d929945dc59db37bf1166937748c6Steve Block    // the nice side effect that multiple closures based on the same
123559151504615d929945dc59db37bf1166937748c6Steve Block    // function can all use this call IC. Before we load through the
123659151504615d929945dc59db37bf1166937748c6Steve Block    // function, we have to verify that it still is a function.
12373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(edi, miss);
123859151504615d929945dc59db37bf1166937748c6Steve Block    __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
1239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(not_equal, miss);
124059151504615d929945dc59db37bf1166937748c6Steve Block
124159151504615d929945dc59db37bf1166937748c6Steve Block    // Check the shared function info. Make sure it hasn't changed.
124259151504615d929945dc59db37bf1166937748c6Steve Block    __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset),
124359151504615d929945dc59db37bf1166937748c6Steve Block           Immediate(Handle<SharedFunctionInfo>(function->shared())));
124459151504615d929945dc59db37bf1166937748c6Steve Block  } else {
1245592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ cmp(edi, Immediate(function));
124659151504615d929945dc59db37bf1166937748c6Steve Block  }
1247592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ j(not_equal, miss);
124859151504615d929945dc59db37bf1166937748c6Steve Block}
124959151504615d929945dc59db37bf1166937748c6Steve Block
125059151504615d929945dc59db37bf1166937748c6Steve Block
1251592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid CallStubCompiler::GenerateMissBranch() {
1252592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Handle<Code> code =
125344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
1254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                               kind_,
1255592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                               extra_state_);
1256592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ jmp(code, RelocInfo::CODE_TARGET);
12577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
12587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1260592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
1261592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                Handle<JSObject> holder,
1262592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                int index,
1263592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                Handle<String> name) {
1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1265e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ecx                 : name
1266e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[0]              : return address
1267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
1268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ...
1269e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc + 1) * 4] : receiver
1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateNameCheck(name, &miss);
12747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver from the stack.
1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
12803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(edx, &miss);
1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do the right check and compute the holder register.
12833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Register reg = CheckPrototypes(object, edx, holder, ebx, eax, edi,
12843bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                 name, &miss);
1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateFastPropertyLoad(masm(), edi, reg, holder, index);
1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the function really is a function.
12893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(edi, &miss);
1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
1291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the receiver on the stack with the global proxy if
1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // necessary.
1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsGlobalObject()) {
1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the function.
1301592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
1302257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
1303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
1304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
1305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), call_kind);
1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1309592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  GenerateMissBranch();
1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(FIELD, name);
1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1316592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> CallStubCompiler::CompileArrayPushCall(
1317592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<Object> object,
1318592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSObject> holder,
1319592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSGlobalPropertyCell> cell,
1320592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSFunction> function,
1321592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<String> name) {
13226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
13236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ecx                 : name
13246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- esp[0]              : return address
13256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
13266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ...
13276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- esp[(argc + 1) * 4] : receiver
13286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
13296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // If object is not an array, bail out to regular call.
1331592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (!object->IsJSArray() || !cell.is_null()) {
1332592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return Handle<Code>::null();
133344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
13346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss;
13366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateNameCheck(name, &miss);
13387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the receiver from the stack.
13406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int argc = arguments().immediate();
13416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
13426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the receiver isn't a smi.
13443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(edx, &miss);
13456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1346592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
1347592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                  name, &miss);
13486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (argc == 0) {
13506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Noop, return the length.
13516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
13526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ ret((argc + 1) * kPointerSize);
13536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
1354756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Label call_builtin;
1355756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
13566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Get the elements array of the object.
13576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset));
13586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1359756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Check that the elements are in fast mode and writable.
13606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
136144f0eee88ff00398ff7f715fab053374d808c90dSteve Block           Immediate(factory()->fixed_array_map()));
1362756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ j(not_equal, &call_builtin);
13636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (argc == 1) {  // Otherwise fall through to call builtin.
1365592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      Label attempt_to_grow_elements, with_write_barrier;
13666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Get the array's length into eax and calculate new length.
13686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
13696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      STATIC_ASSERT(kSmiTagSize == 1);
13706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      STATIC_ASSERT(kSmiTag == 0);
1371592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ add(eax, Immediate(Smi::FromInt(argc)));
13726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Get the element's length into ecx.
13746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ mov(ecx, FieldOperand(ebx, FixedArray::kLengthOffset));
13756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Check if we could survive without allocation.
1377592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ cmp(eax, ecx);
13786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ j(greater, &attempt_to_grow_elements);
13796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1380592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Check if value is a smi.
1381592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ mov(ecx, Operand(esp, argc * kPointerSize));
1382592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ JumpIfNotSmi(ecx, &with_write_barrier);
1383592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
13846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Save new length.
13856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
13866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Push the element.
13886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ lea(edx, FieldOperand(ebx,
13896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               eax, times_half_pointer_size,
13906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               FixedArray::kHeaderSize - argc * kPointerSize));
13916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ mov(Operand(edx, 0), ecx);
13926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ ret((argc + 1) * kPointerSize);
13946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ bind(&with_write_barrier);
13966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1397592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
1398592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ CheckFastObjectElements(edi, &call_builtin);
1399592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1400592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Save new length.
1401592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
1402592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1403592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Push the element.
1404592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ lea(edx, FieldOperand(ebx,
1405592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                               eax, times_half_pointer_size,
1406592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                               FixedArray::kHeaderSize - argc * kPointerSize));
1407592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ mov(Operand(edx, 0), ecx);
1408592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1409592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ RecordWrite(ebx, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
1410592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                     OMIT_SMI_CHECK);
14116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ ret((argc + 1) * kPointerSize);
14136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ bind(&attempt_to_grow_elements);
14155913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (!FLAG_inline_new) {
14165913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        __ jmp(&call_builtin);
14175913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
14185913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck
1419592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ mov(edi, Operand(esp, argc * kPointerSize));
1420592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Growing elements that are SMI-only requires special handling in case
1421592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // the new element is non-Smi. For now, delegate to the builtin.
1422592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      Label no_fast_elements_check;
1423592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ JumpIfSmi(edi, &no_fast_elements_check);
1424592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
1425592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ CheckFastObjectElements(ecx, &call_builtin, Label::kFar);
1426592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ bind(&no_fast_elements_check);
1427592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1428592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // We could be lucky and the elements array could be at the top of
1429592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // new-space.  In this case we can just grow it in place by moving the
1430592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // allocation pointer up.
1431592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
14326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ExternalReference new_space_allocation_top =
143344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ExternalReference::new_space_allocation_top_address(isolate());
14346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ExternalReference new_space_allocation_limit =
143544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ExternalReference::new_space_allocation_limit_address(isolate());
14366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      const int kAllocationDelta = 4;
14386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Load top.
14396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ mov(ecx, Operand::StaticVariable(new_space_allocation_top));
14406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Check if it's the end of elements.
14426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ lea(edx, FieldOperand(ebx,
14436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               eax, times_half_pointer_size,
14446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               FixedArray::kHeaderSize - argc * kPointerSize));
1445592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ cmp(edx, ecx);
14466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ j(not_equal, &call_builtin);
1447592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ add(ecx, Immediate(kAllocationDelta * kPointerSize));
14486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ cmp(ecx, Operand::StaticVariable(new_space_allocation_limit));
14496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ j(above, &call_builtin);
14506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // We fit and could grow elements.
14526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ mov(Operand::StaticVariable(new_space_allocation_top), ecx);
14536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Push the argument...
1455592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ mov(Operand(edx, 0), edi);
14566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // ... and fill the rest with holes.
14576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      for (int i = 1; i < kAllocationDelta; i++) {
14586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        __ mov(Operand(edx, i * kPointerSize),
145944f0eee88ff00398ff7f715fab053374d808c90dSteve Block               Immediate(factory()->the_hole_value()));
14606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
14616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1462592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // We know the elements array is in new space so we don't need the
1463592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // remembered set, but we just pushed a value onto it so we may have to
1464592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // tell the incremental marker to rescan the object that we just grew.  We
1465592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // don't need to worry about the holes because they are in old space and
1466592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // already marked black.
1467592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ RecordWrite(ebx, edx, edi, kDontSaveFPRegs, OMIT_REMEMBERED_SET);
1468592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
14696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Restore receiver to edx as finish sequence assumes it's here.
14706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
14716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Increment element's and array's sizes.
14736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ add(FieldOperand(ebx, FixedArray::kLengthOffset),
14747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch             Immediate(Smi::FromInt(kAllocationDelta)));
1475592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1476592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // NOTE: This only happen in new-space, where we don't
1477592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // care about the black-byte-count on pages. Otherwise we should
1478592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // update that too if the object is black.
1479592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
14806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
14816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ ret((argc + 1) * kPointerSize);
14836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
14846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1485756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ bind(&call_builtin);
148644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ TailCallExternalReference(
148744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ExternalReference(Builtins::c_ArrayPush, isolate()),
148844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        argc + 1,
148944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        1);
14906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
14916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss);
1493592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  GenerateMissBranch();
14946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return the generated code.
149625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  return GetCode(function);
14976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
14986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1500592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> CallStubCompiler::CompileArrayPopCall(
1501592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<Object> object,
1502592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSObject> holder,
1503592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSGlobalPropertyCell> cell,
1504592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSFunction> function,
1505592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<String> name) {
15066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
15076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ecx                 : name
15086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- esp[0]              : return address
15096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
15106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ...
15116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- esp[(argc + 1) * 4] : receiver
15126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
15136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // If object is not an array, bail out to regular call.
1515592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (!object->IsJSArray() || !cell.is_null()) {
1516592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return Handle<Code>::null();
151744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
15186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss, return_undefined, call_builtin;
15206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateNameCheck(name, &miss);
15227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
15236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the receiver from the stack.
15246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int argc = arguments().immediate();
15256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
15266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the receiver isn't a smi.
15283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(edx, &miss);
1529592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
1530592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                  name, &miss);
15316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the elements array of the object.
15336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset));
15346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1535756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Check that the elements are in fast mode and writable.
15366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
153744f0eee88ff00398ff7f715fab053374d808c90dSteve Block         Immediate(factory()->fixed_array_map()));
1538756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ j(not_equal, &call_builtin);
15396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the array's length into ecx and calculate new length.
15416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(ecx, FieldOperand(edx, JSArray::kLengthOffset));
1542592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ sub(ecx, Immediate(Smi::FromInt(1)));
15436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ j(negative, &return_undefined);
15446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the last element.
15466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  STATIC_ASSERT(kSmiTagSize == 1);
15476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  STATIC_ASSERT(kSmiTag == 0);
15486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(eax, FieldOperand(ebx,
15496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           ecx, times_half_pointer_size,
15506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           FixedArray::kHeaderSize));
1551592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ cmp(eax, Immediate(factory()->the_hole_value()));
15526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ j(equal, &call_builtin);
15536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Set the array's length.
15556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(FieldOperand(edx, JSArray::kLengthOffset), ecx);
15566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Fill with the hole.
15586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(FieldOperand(ebx,
15596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      ecx, times_half_pointer_size,
15606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      FixedArray::kHeaderSize),
156144f0eee88ff00398ff7f715fab053374d808c90dSteve Block         Immediate(factory()->the_hole_value()));
15626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ret((argc + 1) * kPointerSize);
15636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&return_undefined);
156544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(eax, Immediate(factory()->undefined_value()));
15666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ret((argc + 1) * kPointerSize);
15676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&call_builtin);
156944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ TailCallExternalReference(
157044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(Builtins::c_ArrayPop, isolate()),
157144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      argc + 1,
157244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      1);
15736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss);
1575592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  GenerateMissBranch();
15767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
15777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Return the generated code.
15787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  return GetCode(function);
15797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
15807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
15817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1582592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
1583592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<Object> object,
1584592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSObject> holder,
1585592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSGlobalPropertyCell> cell,
1586592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSFunction> function,
1587592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<String> name) {
15887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // ----------- S t a t e -------------
15897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- ecx                 : function name
15907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[0]              : return address
15917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
15927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- ...
15937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[(argc + 1) * 4] : receiver
15947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // -----------------------------------
15957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1596756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // If object is not a string, bail out to regular call.
1597592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (!object->IsString() || !cell.is_null()) {
1598592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return Handle<Code>::null();
159944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1600756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
16017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  const int argc = arguments().immediate();
16027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
16037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label miss;
1604b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label name_miss;
16057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
1606b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label* index_out_of_range_label = &index_out_of_range;
16079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
1608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (kind_ == Code::CALL_IC &&
1609592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      (CallICBase::StringStubState::decode(extra_state_) ==
1610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       DEFAULT_STRING_STUB)) {
1611b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    index_out_of_range_label = &miss;
1612b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1613b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1614b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  GenerateNameCheck(name, &name_miss);
16157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
16167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Check that the maps starting from the prototype haven't changed.
16177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateDirectLoadGlobalFunctionPrototype(masm(),
16187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                            Context::STRING_FUNCTION_INDEX,
16190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            eax,
16200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            &miss);
1621592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  ASSERT(!object.is_identical_to(holder));
1622592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())),
1623592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                  eax, holder, ebx, edx, edi, name, &miss);
16247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
16257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register receiver = ebx;
16267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = edi;
16277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = eax;
16287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize));
16297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (argc > 0) {
16307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ mov(index, Operand(esp, (argc - 0) * kPointerSize));
16317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  } else {
163244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ Set(index, Immediate(factory()->undefined_value()));
16337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
16347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1635592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  StringCharCodeAtGenerator generator(receiver,
1636592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                      index,
1637592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                      result,
1638592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                      &miss,  // When not a string.
1639592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                      &miss,  // When not a number.
1640592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                      index_out_of_range_label,
1641592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                      STRING_INDEX_IS_NUMBER);
1642592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  generator.GenerateFast(masm());
16437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ ret((argc + 1) * kPointerSize);
16447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StubRuntimeCallHelper call_helper;
1646592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  generator.GenerateSlow(masm(), call_helper);
16477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1648b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (index_out_of_range.is_linked()) {
1649b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ bind(&index_out_of_range);
165044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ Set(eax, Immediate(factory()->nan_value()));
1651b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ ret((argc + 1) * kPointerSize);
1652b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
16537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
16547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&miss);
1655b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Restore function name in ecx.
1656592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ Set(ecx, Immediate(name));
1657b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&name_miss);
1658592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  GenerateMissBranch();
16597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
16607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Return the generated code.
16617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  return GetCode(function);
16627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
16637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
16647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1665592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> CallStubCompiler::CompileStringCharAtCall(
1666592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<Object> object,
1667592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSObject> holder,
1668592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSGlobalPropertyCell> cell,
1669592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSFunction> function,
1670592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<String> name) {
16717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // ----------- S t a t e -------------
16727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- ecx                 : function name
16737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[0]              : return address
16747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
16757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- ...
16767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[(argc + 1) * 4] : receiver
16777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // -----------------------------------
16787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1679756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // If object is not a string, bail out to regular call.
1680592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (!object->IsString() || !cell.is_null()) {
1681592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return Handle<Code>::null();
168244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1683756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
16847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  const int argc = arguments().immediate();
16857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
16867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label miss;
1687b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label name_miss;
16887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
1689b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label* index_out_of_range_label = &index_out_of_range;
16907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (kind_ == Code::CALL_IC &&
1692592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      (CallICBase::StringStubState::decode(extra_state_) ==
1693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       DEFAULT_STRING_STUB)) {
1694b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    index_out_of_range_label = &miss;
1695b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1696b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1697b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  GenerateNameCheck(name, &name_miss);
16987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
16997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Check that the maps starting from the prototype haven't changed.
17007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateDirectLoadGlobalFunctionPrototype(masm(),
17017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                            Context::STRING_FUNCTION_INDEX,
17020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            eax,
17030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            &miss);
1704592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  ASSERT(!object.is_identical_to(holder));
1705592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())),
1706592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                  eax, holder, ebx, edx, edi, name, &miss);
17077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
17087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register receiver = eax;
17097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = edi;
1710592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Register scratch = edx;
17117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = eax;
17127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize));
17137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (argc > 0) {
17147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ mov(index, Operand(esp, (argc - 0) * kPointerSize));
17157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  } else {
171644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ Set(index, Immediate(factory()->undefined_value()));
17177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
17187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1719592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  StringCharAtGenerator generator(receiver,
1720592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                  index,
1721592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                  scratch,
1722592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                  result,
1723592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                  &miss,  // When not a string.
1724592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                  &miss,  // When not a number.
1725592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                  index_out_of_range_label,
1726592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                  STRING_INDEX_IS_NUMBER);
1727592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  generator.GenerateFast(masm());
17287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ ret((argc + 1) * kPointerSize);
17297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StubRuntimeCallHelper call_helper;
1731592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  generator.GenerateSlow(masm(), call_helper);
17327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1733b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (index_out_of_range.is_linked()) {
1734b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ bind(&index_out_of_range);
173544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ Set(eax, Immediate(factory()->empty_string()));
1736b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ ret((argc + 1) * kPointerSize);
1737b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
17387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
17397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&miss);
1740b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Restore function name in ecx.
1741592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ Set(ecx, Immediate(name));
1742b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&name_miss);
1743592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  GenerateMissBranch();
17446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return the generated code.
174625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  return GetCode(function);
17476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
17486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1750592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
1751592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<Object> object,
1752592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSObject> holder,
1753592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSGlobalPropertyCell> cell,
1754592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSFunction> function,
1755592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<String> name) {
175659151504615d929945dc59db37bf1166937748c6Steve Block  // ----------- S t a t e -------------
175759151504615d929945dc59db37bf1166937748c6Steve Block  //  -- ecx                 : function name
175859151504615d929945dc59db37bf1166937748c6Steve Block  //  -- esp[0]              : return address
175959151504615d929945dc59db37bf1166937748c6Steve Block  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
176059151504615d929945dc59db37bf1166937748c6Steve Block  //  -- ...
176159151504615d929945dc59db37bf1166937748c6Steve Block  //  -- esp[(argc + 1) * 4] : receiver
176259151504615d929945dc59db37bf1166937748c6Steve Block  // -----------------------------------
176359151504615d929945dc59db37bf1166937748c6Steve Block
176459151504615d929945dc59db37bf1166937748c6Steve Block  const int argc = arguments().immediate();
176559151504615d929945dc59db37bf1166937748c6Steve Block
176659151504615d929945dc59db37bf1166937748c6Steve Block  // If the object is not a JSObject or we got an unexpected number of
176759151504615d929945dc59db37bf1166937748c6Steve Block  // arguments, bail out to the regular call.
176844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!object->IsJSObject() || argc != 1) {
1769592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return Handle<Code>::null();
177044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
177159151504615d929945dc59db37bf1166937748c6Steve Block
177259151504615d929945dc59db37bf1166937748c6Steve Block  Label miss;
177359151504615d929945dc59db37bf1166937748c6Steve Block  GenerateNameCheck(name, &miss);
177459151504615d929945dc59db37bf1166937748c6Steve Block
1775592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (cell.is_null()) {
177659151504615d929945dc59db37bf1166937748c6Steve Block    __ mov(edx, Operand(esp, 2 * kPointerSize));
177759151504615d929945dc59db37bf1166937748c6Steve Block    STATIC_ASSERT(kSmiTag == 0);
17783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(edx, &miss);
1779592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
1780592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                    name, &miss);
178159151504615d929945dc59db37bf1166937748c6Steve Block  } else {
1782592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    ASSERT(cell->value() == *function);
1783592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
1784592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                &miss);
178559151504615d929945dc59db37bf1166937748c6Steve Block    GenerateLoadFunctionFromCell(cell, function, &miss);
178659151504615d929945dc59db37bf1166937748c6Steve Block  }
178759151504615d929945dc59db37bf1166937748c6Steve Block
178859151504615d929945dc59db37bf1166937748c6Steve Block  // Load the char code argument.
178959151504615d929945dc59db37bf1166937748c6Steve Block  Register code = ebx;
179059151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(code, Operand(esp, 1 * kPointerSize));
179159151504615d929945dc59db37bf1166937748c6Steve Block
179259151504615d929945dc59db37bf1166937748c6Steve Block  // Check the code is a smi.
179359151504615d929945dc59db37bf1166937748c6Steve Block  Label slow;
179459151504615d929945dc59db37bf1166937748c6Steve Block  STATIC_ASSERT(kSmiTag == 0);
17953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(code, &slow);
179659151504615d929945dc59db37bf1166937748c6Steve Block
179759151504615d929945dc59db37bf1166937748c6Steve Block  // Convert the smi code to uint16.
179859151504615d929945dc59db37bf1166937748c6Steve Block  __ and_(code, Immediate(Smi::FromInt(0xffff)));
179959151504615d929945dc59db37bf1166937748c6Steve Block
1800592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  StringCharFromCodeGenerator generator(code, eax);
1801592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  generator.GenerateFast(masm());
180259151504615d929945dc59db37bf1166937748c6Steve Block  __ ret(2 * kPointerSize);
180359151504615d929945dc59db37bf1166937748c6Steve Block
1804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StubRuntimeCallHelper call_helper;
1805592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  generator.GenerateSlow(masm(), call_helper);
180659151504615d929945dc59db37bf1166937748c6Steve Block
180759151504615d929945dc59db37bf1166937748c6Steve Block  // Tail call the full function. We do not have to patch the receiver
180859151504615d929945dc59db37bf1166937748c6Steve Block  // because the function makes no use of it.
180959151504615d929945dc59db37bf1166937748c6Steve Block  __ bind(&slow);
1810592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
1811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
1812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
1813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
1814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), call_kind);
181559151504615d929945dc59db37bf1166937748c6Steve Block
181659151504615d929945dc59db37bf1166937748c6Steve Block  __ bind(&miss);
181759151504615d929945dc59db37bf1166937748c6Steve Block  // ecx: function name.
1818592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  GenerateMissBranch();
181959151504615d929945dc59db37bf1166937748c6Steve Block
182059151504615d929945dc59db37bf1166937748c6Steve Block  // Return the generated code.
1821592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
182259151504615d929945dc59db37bf1166937748c6Steve Block}
182359151504615d929945dc59db37bf1166937748c6Steve Block
182459151504615d929945dc59db37bf1166937748c6Steve Block
1825592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> CallStubCompiler::CompileMathFloorCall(
1826592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<Object> object,
1827592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSObject> holder,
1828592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSGlobalPropertyCell> cell,
1829592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSFunction> function,
1830592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<String> name) {
18310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // ----------- S t a t e -------------
18320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  //  -- ecx                 : name
18330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  //  -- esp[0]              : return address
18340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
18350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  //  -- ...
18360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  //  -- esp[(argc + 1) * 4] : receiver
18370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // -----------------------------------
18380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
18398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (!CpuFeatures::IsSupported(SSE2)) {
1840592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return Handle<Code>::null();
184144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
184244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
18430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  CpuFeatures::Scope use_sse2(SSE2);
18440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
18450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  const int argc = arguments().immediate();
18460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
18470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // If the object is not a JSObject or we got an unexpected number of
18480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // arguments, bail out to the regular call.
184944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!object->IsJSObject() || argc != 1) {
1850592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return Handle<Code>::null();
185144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
18520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
18530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label miss;
18540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  GenerateNameCheck(name, &miss);
18550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
1856592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (cell.is_null()) {
18570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ mov(edx, Operand(esp, 2 * kPointerSize));
18580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
18590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    STATIC_ASSERT(kSmiTag == 0);
18603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(edx, &miss);
18610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
1862592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
1863592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                    name, &miss);
18640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
1865592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    ASSERT(cell->value() == *function);
1866592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
1867592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                &miss);
18680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    GenerateLoadFunctionFromCell(cell, function, &miss);
18690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
18700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
18710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Load the (only) argument into eax.
18720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ mov(eax, Operand(esp, 1 * kPointerSize));
18730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
18740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Check if the argument is a smi.
18750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label smi;
18760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  STATIC_ASSERT(kSmiTag == 0);
18773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(eax, &smi);
18780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
18790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Check if the argument is a heap number and load its value into xmm0.
18800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label slow;
1881257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ CheckMap(eax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK);
18820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ movdbl(xmm0, FieldOperand(eax, HeapNumber::kValueOffset));
18830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
18840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Check if the argument is strictly positive. Note this also
18850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // discards NaN.
18860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ xorpd(xmm1, xmm1);
18870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ ucomisd(xmm0, xmm1);
18880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ j(below_equal, &slow);
18890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
18900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Do a truncating conversion.
18910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ cvttsd2si(eax, Operand(xmm0));
18920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
18930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Check if the result fits into a smi. Note this also checks for
18940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // 0x80000000 which signals a failed conversion.
18950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label wont_fit_into_smi;
18960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ test(eax, Immediate(0xc0000000));
18970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ j(not_zero, &wont_fit_into_smi);
18980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
18990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Smi tag and return.
19000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ SmiTag(eax);
19010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&smi);
19020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ ret(2 * kPointerSize);
19030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Check if the argument is < 2^kMantissaBits.
19050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label already_round;
19060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&wont_fit_into_smi);
19070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadPowerOf2(xmm1, ebx, HeapNumber::kMantissaBits);
19080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ ucomisd(xmm0, xmm1);
19090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ j(above_equal, &already_round);
19100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Save a copy of the argument.
19120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ movaps(xmm2, xmm0);
19130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Compute (argument + 2^kMantissaBits) - 2^kMantissaBits.
19150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ addsd(xmm0, xmm1);
19160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ subsd(xmm0, xmm1);
19170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Compare the argument and the tentative result to get the right mask:
19190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  //   if xmm2 < xmm0:
19200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  //     xmm2 = 1...1
19210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  //   else:
19220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  //     xmm2 = 0...0
19230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ cmpltsd(xmm2, xmm0);
19240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Subtract 1 if the argument was less than the tentative result.
19260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadPowerOf2(xmm1, ebx, 0);
19270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ andpd(xmm1, xmm2);
19280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ subsd(xmm0, xmm1);
19290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Return a new heap number.
19310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ AllocateHeapNumber(eax, ebx, edx, &slow);
19320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
19330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ ret(2 * kPointerSize);
19340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Return the argument (when it's an already round heap number).
19360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&already_round);
19370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ mov(eax, Operand(esp, 1 * kPointerSize));
19380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ ret(2 * kPointerSize);
19390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Tail call the full function. We do not have to patch the receiver
19410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // because the function makes no use of it.
19420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&slow);
1943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
1944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), CALL_AS_METHOD);
19450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&miss);
19470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // ecx: function name.
1948592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  GenerateMissBranch();
19490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Return the generated code.
1951592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
19520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
19530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
1955592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> CallStubCompiler::CompileMathAbsCall(
1956592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<Object> object,
1957592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSObject> holder,
1958592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSGlobalPropertyCell> cell,
1959592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSFunction> function,
1960592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<String> name) {
1961f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // ----------- S t a t e -------------
1962f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- ecx                 : name
1963f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- esp[0]              : return address
1964f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
1965f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- ...
1966f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- esp[(argc + 1) * 4] : receiver
1967f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // -----------------------------------
1968f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1969f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const int argc = arguments().immediate();
1970f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1971f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // If the object is not a JSObject or we got an unexpected number of
1972f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // arguments, bail out to the regular call.
197344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!object->IsJSObject() || argc != 1) {
1974592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return Handle<Code>::null();
197544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1976f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1977f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Label miss;
1978f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  GenerateNameCheck(name, &miss);
1979f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1980592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (cell.is_null()) {
1981f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    __ mov(edx, Operand(esp, 2 * kPointerSize));
1982f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1983f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    STATIC_ASSERT(kSmiTag == 0);
19843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(edx, &miss);
1985f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1986592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
1987592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                    name, &miss);
1988f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  } else {
1989592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    ASSERT(cell->value() == *function);
1990592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
1991592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                &miss);
1992f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    GenerateLoadFunctionFromCell(cell, function, &miss);
1993f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
1994f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1995f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Load the (only) argument into eax.
1996f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ mov(eax, Operand(esp, 1 * kPointerSize));
1997f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
1998f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Check if the argument is a smi.
1999f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Label not_smi;
2000f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
20013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(eax, &not_smi);
2002f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2003f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0
2004f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // otherwise.
2005f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ mov(ebx, eax);
2006f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ sar(ebx, kBitsPerInt - 1);
2007f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2008f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Do bitwise not or do nothing depending on ebx.
2009592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ xor_(eax, ebx);
2010f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2011f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Add 1 or do nothing depending on ebx.
2012592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ sub(eax, ebx);
2013f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2014f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // If the result is still negative, go to the slow case.
2015f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // This only happens for the most negative smi.
2016f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Label slow;
2017f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ j(negative, &slow);
2018f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2019f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Smi case done.
2020f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ ret(2 * kPointerSize);
2021f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2022f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Check if the argument is a heap number and load its exponent and
2023f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // sign into ebx.
2024f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ bind(&not_smi);
2025257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ CheckMap(eax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK);
2026f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ mov(ebx, FieldOperand(eax, HeapNumber::kExponentOffset));
2027f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2028f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Check the sign of the argument. If the argument is positive,
2029f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // just return it.
2030f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Label negative_sign;
2031f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ test(ebx, Immediate(HeapNumber::kSignMask));
2032f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ j(not_zero, &negative_sign);
2033f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ ret(2 * kPointerSize);
2034f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2035f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // If the argument is negative, clear the sign, and return a new
2036f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // number.
2037f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ bind(&negative_sign);
2038f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ and_(ebx, ~HeapNumber::kSignMask);
2039f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ mov(ecx, FieldOperand(eax, HeapNumber::kMantissaOffset));
2040f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ AllocateHeapNumber(eax, edi, edx, &slow);
2041f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ebx);
2042f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx);
2043f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ ret(2 * kPointerSize);
2044f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2045f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Tail call the full function. We do not have to patch the receiver
2046f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // because the function makes no use of it.
2047f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ bind(&slow);
2048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
2049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), CALL_AS_METHOD);
2050f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2051f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ bind(&miss);
2052f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // ecx: function name.
2053592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  GenerateMissBranch();
2054f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2055f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Return the generated code.
2056592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
2057f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
2058f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2059f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2060592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> CallStubCompiler::CompileFastApiCall(
206144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    const CallOptimization& optimization,
2062592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<Object> object,
2063592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSObject> holder,
2064592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSGlobalPropertyCell> cell,
2065592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSFunction> function,
2066592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<String> name) {
206744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(optimization.is_simple_api_call());
206844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Bail out if object is a global object as we don't want to
206944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // repatch it to global receiver.
2070592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (object->IsGlobalObject()) return Handle<Code>::null();
2071592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (!cell.is_null()) return Handle<Code>::null();
2072592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (!object->IsJSObject()) return Handle<Code>::null();
207344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int depth = optimization.GetPrototypeDepthOfExpectedType(
2074592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      Handle<JSObject>::cast(object), holder);
2075592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (depth == kInvalidProtoDepth) return Handle<Code>::null();
207644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
207744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label miss, miss_before_stack_reserved;
207844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
207944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenerateNameCheck(name, &miss_before_stack_reserved);
208044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
208144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Get the receiver from the stack.
208244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const int argc = arguments().immediate();
208344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
208444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
208544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the receiver isn't a smi.
20863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(edx, &miss_before_stack_reserved);
208744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
208844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
208944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_const(), 1);
209044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_const_fast_api(), 1);
209144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
209244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Allocate space for v8::Arguments implicit values. Must be initialized
209344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // before calling any runtime function.
2094592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ sub(esp, Immediate(kFastApiCallArguments * kPointerSize));
209544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
209644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the maps haven't changed and find a Holder as a side effect.
2097592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
2098592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                  name, depth, &miss);
209944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
210044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Move the return address on top of the stack.
210144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(eax, Operand(esp, 3 * kPointerSize));
210244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(Operand(esp, 0 * kPointerSize), eax);
210344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
210444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains
210544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // duplicate of return address and will be overwritten.
2106592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  GenerateFastApiCall(masm(), optimization, argc);
210744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
210844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&miss);
2109592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ add(esp, Immediate(kFastApiCallArguments * kPointerSize));
211044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
211144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&miss_before_stack_reserved);
2112592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  GenerateMissBranch();
211344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
211444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Return the generated code.
211544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return GetCode(function);
211644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
211744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
211844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2119592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object,
2120592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                   Handle<JSObject> holder,
2121592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                   Handle<JSFunction> function,
2122592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                   Handle<String> name,
2123592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                   CheckType check) {
2124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2125e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ecx                 : name
2126e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[0]              : return address
2127e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
2128e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ...
2129e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc + 1) * 4] : receiver
2130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
21316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
213244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (HasCustomCallGenerator(function)) {
2133592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<Code> code = CompileCustomCall(object, holder,
2134592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                          Handle<JSGlobalPropertyCell>::null(),
2135592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                          function, name);
2136592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // A null handle means bail out to the regular compiler code below.
2137592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (!code.is_null()) return code;
21386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
21396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
214044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label miss;
214144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenerateNameCheck(name, &miss);
21427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver from the stack.
2144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
2145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
2146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
2148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (check != NUMBER_CHECK) {
21493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(edx, &miss);
2150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that it's okay not to patch the on stack receiver
2153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // unless we're doing a receiver map check.
2154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
2155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (check) {
2156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case RECEIVER_MAP_CHECK:
215744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ IncrementCounter(isolate()->counters()->call_const(), 1);
2158402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Check that the maps haven't changed.
2160592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax,
2161592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                      edi, name, &miss);
2162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Patch the receiver on the stack with the global proxy if
2164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // necessary.
2165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (object->IsGlobalObject()) {
2166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
2167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
2168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
2169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
2170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case STRING_CHECK:
2172592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
2173e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the object is a string or a symbol.
21747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax);
2175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ j(above_equal, &miss);
2176e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the maps starting from the prototype haven't changed.
21777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        GenerateDirectLoadGlobalFunctionPrototype(
21780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            masm(), Context::STRING_FUNCTION_INDEX, eax, &miss);
2179592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        CheckPrototypes(
2180592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch            Handle<JSObject>(JSObject::cast(object->GetPrototype())),
2181592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch            eax, holder, ebx, edx, edi, name, &miss);
2182592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      } else {
2183e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Calling non-strict non-builtins with a value as the receiver
2184e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // requires boxing.
2185e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ jmp(&miss);
2186592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      }
2187592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      break;
2188592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
2189592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    case NUMBER_CHECK:
2190592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
2191e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        Label fast;
2192e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the object is a smi or a heap number.
21933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        __ JumpIfSmi(edx, &fast);
2194e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax);
2195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ j(not_equal, &miss);
2196e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ bind(&fast);
2197e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the maps starting from the prototype haven't changed.
21987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        GenerateDirectLoadGlobalFunctionPrototype(
21990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss);
2200592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        CheckPrototypes(
2201592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch            Handle<JSObject>(JSObject::cast(object->GetPrototype())),
2202592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch            eax, holder, ebx, edx, edi, name, &miss);
2203592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      } else {
2204e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Calling non-strict non-builtins with a value as the receiver
2205e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // requires boxing.
2206e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ jmp(&miss);
2207592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      }
2208592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      break;
2209592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
2210592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    case BOOLEAN_CHECK:
2211592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
2212e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        Label fast;
2213e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the object is a boolean.
221444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ cmp(edx, factory()->true_value());
2215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ j(equal, &fast);
221644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ cmp(edx, factory()->false_value());
2217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ j(not_equal, &miss);
2218e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ bind(&fast);
2219e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the maps starting from the prototype haven't changed.
22207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        GenerateDirectLoadGlobalFunctionPrototype(
22210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss);
2222592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        CheckPrototypes(
2223592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch            Handle<JSObject>(JSObject::cast(object->GetPrototype())),
2224592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch            eax, holder, ebx, edx, edi, name, &miss);
2225592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      } else {
2226592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        // Calling non-strict non-builtins with a value as the receiver
2227592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        // requires boxing.
2228592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ jmp(&miss);
2229e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
2230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
2231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2233592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
2235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
2236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
2237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), call_kind);
2238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
2240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2241592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  GenerateMissBranch();
2242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
224425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  return GetCode(function);
2245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2248592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
2249592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                      Handle<JSObject> holder,
2250592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                      Handle<String> name) {
2251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2252e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ecx                 : name
2253e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[0]              : return address
2254e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
2255e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ...
2256e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc + 1) * 4] : receiver
2257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateNameCheck(name, &miss);
22617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the number of arguments.
2263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
2264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2265592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  LookupResult lookup(isolate());
2266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LookupPostInterceptor(holder, name, &lookup);
2267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver from the stack.
2269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
2270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2271592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  CallInterceptorCompiler compiler(this, arguments(), ecx, extra_state_);
2272592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  compiler.Compile(masm(), object, holder, name, &lookup, edx, ebx, edi, eax,
2273592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                   &miss);
2274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Restore receiver.
2276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
2277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the function really is a function.
22793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(eax, &miss);
2280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
2281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
2282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the receiver on the stack with the global proxy if
2284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // necessary.
2285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsGlobalObject()) {
2286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
2287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
2288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the function.
2291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(edi, eax);
2292592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
2294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
2295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
2296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), call_kind);
2297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle load cache miss.
2299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2300592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  GenerateMissBranch();
2301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2307592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> CallStubCompiler::CompileCallGlobal(
2308592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSObject> object,
2309592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<GlobalObject> holder,
2310592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSGlobalPropertyCell> cell,
2311592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSFunction> function,
2312592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<String> name) {
2313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ecx                 : name
2315e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[0]              : return address
2316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
2317e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ...
2318e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc + 1) * 4] : receiver
2319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
232059151504615d929945dc59db37bf1166937748c6Steve Block
232144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (HasCustomCallGenerator(function)) {
2322592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<Code> code = CompileCustomCall(object, holder, cell, function, name);
2323592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // A null handle means bail out to the regular compiler code below.
2324592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (!code.is_null()) return code;
232559151504615d929945dc59db37bf1166937748c6Steve Block  }
232659151504615d929945dc59db37bf1166937748c6Steve Block
2327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
23287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateNameCheck(name, &miss);
23297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the number of arguments.
2331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
233259151504615d929945dc59db37bf1166937748c6Steve Block  GenerateGlobalReceiverCheck(object, holder, name, &miss);
233359151504615d929945dc59db37bf1166937748c6Steve Block  GenerateLoadFunctionFromCell(cell, function, &miss);
2334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the receiver on the stack with the global proxy.
2336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsGlobalObject()) {
2337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
2338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
2339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Setup the context (function already in edi).
2342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
2343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the cached code (tail call).
234544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
234644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_global_inline(), 1);
2347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount expected(function->shared()->formal_parameter_count());
2348592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
2350257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
2351592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // We call indirectly through the code field in the function to
2352592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // allow recompilation to take effect without changing any of the
2353592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // call sites.
2354592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
2355592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                expected, arguments(), JUMP_FUNCTION,
2356592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                NullCallWrapper(), call_kind);
2357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
2359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
236044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_global_inline_miss(), 1);
2361592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  GenerateMissBranch();
2362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(NORMAL, name);
2365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2368592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
23695913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                  int index,
2370592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                  Handle<Map> transition,
2371592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                  Handle<String> name) {
2372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- eax    : value
2374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
23754515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- edx    : receiver
2376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Generate store field code.  Trashes the name register.
2381592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  GenerateStoreField(masm(), object, index, transition, edx, ecx, ebx, &miss);
2382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2385592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ mov(ecx, Immediate(name));  // restore name
238644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(ic, RelocInfo::CODE_TARGET);
2388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2390592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name);
2391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2394592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> StoreStubCompiler::CompileStoreCallback(
2395592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSObject> object,
2396592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<AccessorInfo> callback,
2397592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<String> name) {
2398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- eax    : value
2400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
24014515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- edx    : receiver
2402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object isn't a smi.
24073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(edx, &miss);
2408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the object hasn't changed.
24104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
2411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         Immediate(Handle<Map>(object->map())));
2412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
2413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform global security token check if needed.
2415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsJSGlobalProxy()) {
24164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ CheckAccessGlobalProxy(edx, ebx, &miss);
2417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub never generated for non-global objects that require access
2420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // checks.
2421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
2422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(ebx);  // remove the return address
24244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ push(edx);  // receiver
2425592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ push(Immediate(callback));  // callback info
2426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ecx);  // name
2427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(eax);  // value
2428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ebx);  // restore return address
2429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do tail-call to the runtime system.
2431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference store_callback_property =
243244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
24336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallExternalReference(store_callback_property, 4, 1);
2434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
243744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(ic, RelocInfo::CODE_TARGET);
2439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2445592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> StoreStubCompiler::CompileStoreInterceptor(
2446592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSObject> receiver,
2447592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<String> name) {
2448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- eax    : value
2450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
24514515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- edx    : receiver
2452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object isn't a smi.
24573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(edx, &miss);
2458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the object hasn't changed.
24604515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
2461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         Immediate(Handle<Map>(receiver->map())));
2462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
2463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform global security token check if needed.
2465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (receiver->IsJSGlobalProxy()) {
24664515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ CheckAccessGlobalProxy(edx, ebx, &miss);
2467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub never generated for non-global objects that require access
2470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // checks.
2471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
2472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(ebx);  // remove the return address
24744515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ push(edx);  // receiver
2475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ecx);  // name
2476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(eax);  // value
2477e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ push(Immediate(Smi::FromInt(strict_mode_)));
2478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ebx);  // restore return address
2479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do tail-call to the runtime system.
2481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference store_ic_property =
248244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate());
2483e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ TailCallExternalReference(store_ic_property, 4, 1);
2484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
248744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(ic, RelocInfo::CODE_TARGET);
2489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2495592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> StoreStubCompiler::CompileStoreGlobal(
2496592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<GlobalObject> object,
2497592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSGlobalPropertyCell> cell,
2498592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<String> name) {
2499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- eax    : value
2501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
25024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- edx    : receiver
2503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the global has not changed.
25084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
2509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         Immediate(Handle<Map>(object->map())));
2510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
2511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Compute the cell operand to use.
2513592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ mov(ebx, Immediate(cell));
2514592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Operand cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset);
2515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the value in the cell is not the hole. If it is, this
25171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // cell could have been deleted and reintroducing the global needs
25181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // to update the property details in the property dictionary of the
25191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // global object. We bail out to the runtime system to do that.
252044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmp(cell_operand, factory()->the_hole_value());
25211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ j(equal, &miss);
25221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
25231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Store the value in the cell.
25241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ mov(cell_operand, eax);
2525592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // No write barrier here, because cells are always rescanned.
25261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the value (register eax).
252844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
252944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_store_global_inline(), 1);
2530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
2531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
253444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_store_global_inline_miss(), 1);
253544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(ic, RelocInfo::CODE_TARGET);
2537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(NORMAL, name);
2540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2543592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
25445913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                       int index,
2545592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                       Handle<Map> transition,
2546592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                       Handle<String> name) {
2547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- eax    : value
25496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ecx    : key
25506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- edx    : receiver
2551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
255544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
255644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_store_field(), 1);
2557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
2559592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ cmp(ecx, Immediate(name));
2560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
2561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Generate store field code.  Trashes the name register.
2563592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  GenerateStoreField(masm(), object, index, transition, edx, ecx, ebx, &miss);
2564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
256744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_store_field(), 1);
256844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(ic, RelocInfo::CODE_TARGET);
2570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2572592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name);
2573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2576592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreElement(
2577592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<Map> receiver_map) {
2578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // ----------- S t a t e -------------
2579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- eax    : value
2580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- ecx    : key
2581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- edx    : receiver
2582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- esp[0] : return address
2583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // -----------------------------------
2584589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ElementsKind elements_kind = receiver_map->elements_kind();
25853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
2586592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Handle<Code> stub =
2587592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      KeyedStoreElementStub(is_jsarray, elements_kind).GetCode();
2588592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
2589592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK);
2590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(ic, RelocInfo::CODE_TARGET);
2593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
2595592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  return GetCode(NORMAL, factory()->empty_string());
2596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2599592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
2600592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    MapHandleList* receiver_maps,
2601592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    CodeHandleList* handler_stubs,
2602592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    MapHandleList* transitioned_maps) {
2603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- eax    : value
2605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ecx    : key
2606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- edx    : receiver
2607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- esp[0] : return address
2608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
2610592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ JumpIfSmi(edx, &miss, Label::kNear);
2611592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
2612592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // ebx: receiver->map().
2613592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  for (int i = 0; i < receiver_maps->length(); ++i) {
2614592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ cmp(edi, receiver_maps->at(i));
2615592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (transitioned_maps->at(i).is_null()) {
2616592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ j(equal, handler_stubs->at(i));
2617592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    } else {
2618592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      Label next_map;
2619592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ j(not_equal, &next_map, Label::kNear);
2620592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ mov(ebx, Immediate(transitioned_maps->at(i)));
2621592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET);
2622592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ bind(&next_map);
2623592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
2624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&miss);
2626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss();
2627257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
2628e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2629e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Return the generated code.
2630592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC);
2631e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2632e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2633e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2634592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name,
2635592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                      Handle<JSObject> object,
2636592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                      Handle<JSObject> last) {
26376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
26386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- eax    : receiver
26396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ecx    : name
26406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- esp[0] : return address
26416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
26426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss;
26436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
26446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the receiver isn't a smi.
26453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(eax, &miss);
26466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
26478defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ASSERT(last->IsGlobalObject() || last->HasFastProperties());
26488defd9ff6930b4e24729971a61cf7469daf119beSteve Block
26496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the maps of the full prototype chain. Also check that
26506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // global property cells up to (but not including) the last object
26516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // in the prototype chain are empty.
26523bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss);
26536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
26546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // If the last object in the prototype chain is a global object,
26556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // check that the global property cell is empty.
26566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (last->IsGlobalObject()) {
2657592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    GenerateCheckPropertyCell(
2658592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        masm(), Handle<GlobalObject>::cast(last), name, edx, &miss);
26596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
26606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
26616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return undefined if maps of the full prototype chain are still the
26626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // same and no global property with this name contains a value.
266344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(eax, isolate()->factory()->undefined_value());
26646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ret(0);
26656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
26666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss);
26676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
26686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
26696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return the generated code.
2670592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  return GetCode(NONEXISTENT, factory()->empty_string());
26716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
26726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2674592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object,
2675592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                Handle<JSObject> holder,
26765913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                int index,
2677592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                Handle<String> name) {
2678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2679402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : receiver
2680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
2681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26853bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  GenerateLoadField(object, holder, eax, ebx, edx, edi, index, name, &miss);
2686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(FIELD, name);
2691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2694592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> LoadStubCompiler::CompileLoadCallback(
2695592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<String> name,
2696592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSObject> object,
2697592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSObject> holder,
2698592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<AccessorInfo> callback) {
2699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2700402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : receiver
2701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
2702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2706592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  GenerateLoadCallback(object, holder, eax, ecx, ebx, edx, edi, callback,
2707592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                       name, &miss);
2708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2716592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object,
2717592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                   Handle<JSObject> holder,
2718592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                   Handle<Object> value,
2719592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                   Handle<String> name) {
2720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2721402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : receiver
2722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
2723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  GenerateLoadConstant(object, holder, eax, ebx, edx, edi, value, name, &miss);
2728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CONSTANT_FUNCTION, name);
2733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2736592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> receiver,
2737592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                      Handle<JSObject> holder,
2738592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                      Handle<String> name) {
2739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2740402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : receiver
2741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
2742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2746592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  LookupResult lookup(isolate());
2747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LookupPostInterceptor(holder, name, &lookup);
2748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // TODO(368): Compile in the whole chain: all the interceptors in
2750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // prototypes and ultimate answer.
2751592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  GenerateLoadInterceptor(receiver, holder, &lookup, eax, ecx, edx, ebx, edi,
2752592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                          name, &miss);
2753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2762592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> LoadStubCompiler::CompileLoadGlobal(
2763592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSObject> object,
2764592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<GlobalObject> holder,
2765592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSGlobalPropertyCell> cell,
2766592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<String> name,
2767592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    bool is_dont_delete) {
2768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2769402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : receiver
2770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
2771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the object is the holder then we know that it's a global
2776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object which can only happen for contextual loads. In this case,
2777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the receiver cannot be a smi.
2778592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (!object.is_identical_to(holder)) {
27793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(eax, &miss);
2780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the maps haven't changed.
27833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CheckPrototypes(object, eax, holder, ebx, edx, edi, name, &miss);
2784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the value from the cell.
2786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (Serializer::enabled()) {
2787592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(ebx, Immediate(cell));
2788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset));
2789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
2790592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(ebx, Operand::Cell(cell));
2791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for deleted property if property can actually be deleted.
2794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!is_dont_delete) {
279544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmp(ebx, factory()->the_hole_value());
2796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(equal, &miss);
2797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (FLAG_debug_code) {
279844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmp(ebx, factory()->the_hole_value());
2799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Check(not_equal, "DontDelete cells can't contain the hole");
2800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
280244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
280344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_load_global_stub(), 1);
2804402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(eax, ebx);
2805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
2806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
280844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_load_global_stub_miss(), 1);
2809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(NORMAL, name);
2813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2816592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name,
2817592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                     Handle<JSObject> receiver,
2818592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                     Handle<JSObject> holder,
28195913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                     int index) {
2820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2821402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
2822402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
2823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
282744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
282844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_field(), 1);
2829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
2831592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ cmp(eax, Immediate(name));
2832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
2833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss);
2835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
283744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_field(), 1);
2838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(FIELD, name);
2842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2845592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadCallback(
2846592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<String> name,
2847592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSObject> receiver,
2848592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSObject> holder,
2849592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<AccessorInfo> callback) {
2850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2851402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
2852402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
2853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
285744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
285844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_callback(), 1);
2859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
2861592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ cmp(eax, Immediate(name));
2862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
2863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2864592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  GenerateLoadCallback(receiver, holder, edx, eax, ebx, ecx, edi, callback,
2865592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                       name, &miss);
2866e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
286844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_callback(), 1);
2869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2876592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadConstant(
2877592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<String> name,
2878592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSObject> receiver,
2879592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSObject> holder,
2880592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<Object> value) {
2881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2882402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
2883402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
2884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
288844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
288944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_constant_function(), 1);
2890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
2892592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ cmp(eax, Immediate(name));
2893257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
2894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2895592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  GenerateLoadConstant(
2896592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      receiver, holder, edx, ebx, ecx, edi, value, name, &miss);
2897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
289844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_constant_function(), 1);
2899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CONSTANT_FUNCTION, name);
2903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2906592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor(
2907592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSObject> receiver,
2908592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSObject> holder,
2909592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<String> name) {
2910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2911402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
2912402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
2913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
291744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
291844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_interceptor(), 1);
2919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
2921592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ cmp(eax, Immediate(name));
2922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
2923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2924592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  LookupResult lookup(isolate());
2925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LookupPostInterceptor(holder, name, &lookup);
2926592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  GenerateLoadInterceptor(receiver, holder, &lookup, edx, eax, ecx, ebx, edi,
2927592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                          name, &miss);
2928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
292944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_interceptor(), 1);
2930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2937592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength(
2938592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<String> name) {
2939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2940402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
2941402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
2942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
294644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
294744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_array_length(), 1);
2948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
2950592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ cmp(eax, Immediate(name));
2951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
2952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2953402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateLoadArrayLength(masm(), edx, ecx, &miss);
2954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
295544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_array_length(), 1);
2956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2963592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadStringLength(
2964592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<String> name) {
2965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2966402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
2967402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
2968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
297244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
297344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_string_length(), 1);
2974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
2976592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ cmp(eax, Immediate(name));
2977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
2978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true);
2980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
298144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_string_length(), 1);
2982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2989592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype(
2990592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<String> name) {
2991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2992402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
2993402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
2994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
299844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
299944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_function_prototype(), 1);
3000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
3002592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ cmp(eax, Immediate(name));
3003257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
3004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3005402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss);
3006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
300744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_function_prototype(), 1);
3008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
3011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
3012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3015592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadElement(
3016592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<Map> receiver_map) {
3017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // ----------- S t a t e -------------
3018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- eax    : key
3019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- edx    : receiver
3020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- esp[0] : return address
3021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // -----------------------------------
3022592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
3023589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ElementsKind elements_kind = receiver_map->elements_kind();
3024592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode();
3025592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
3026592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK);
3027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3028257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3030257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
3031592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  return GetCode(NORMAL, factory()->empty_string());
3032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3035592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic(
3036592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    MapHandleList* receiver_maps,
3037592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    CodeHandleList* handler_ics) {
3038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- eax    : key
3040257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- edx    : receiver
3041257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- esp[0] : return address
3042257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3043257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
3044257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfSmi(edx, &miss);
3045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register map_reg = ebx;
3047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(map_reg, FieldOperand(edx, HeapObject::kMapOffset));
3048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int receiver_count = receiver_maps->length();
3049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int current = 0; current < receiver_count; ++current) {
3050592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ cmp(map_reg, receiver_maps->at(current));
3051592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ j(equal, handler_ics->at(current));
3052257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&miss);
3055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Return the generated code.
3058592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC);
3059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Specialized stub for constructing objects from functions which only have only
3063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// simple assignments of the form this.x = ...; in their body.
3064592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> ConstructStubCompiler::CompileConstructStub(
3065592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Handle<JSFunction> function) {
3066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
3067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- eax : argc
3068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- edi : constructor
3069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
3070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[4] : last argument
3071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
3072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label generic_stub_call;
3073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
3074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check to see whether there are any break points in the function code. If
3075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // there are jump to the generic constructor stub which calls the actual
3076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // code for the function thereby hitting the break points.
3077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
3078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kDebugInfoOffset));
307944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmp(ebx, factory()->undefined_value());
3080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &generic_stub_call);
3081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
3082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the initial map and verify that it is in fact a map.
3084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
3085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Will both indicate a NULL and a Smi.
30863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(ebx, &generic_stub_call);
3087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpObjectType(ebx, MAP_TYPE, ecx);
3088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &generic_stub_call);
3089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
3091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Cannot construct functions this way.
3092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // edi: constructor
3093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ebx: initial map
3094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpInstanceType(ebx, JS_FUNCTION_TYPE);
3095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Assert(not_equal, "Function constructed by construct stub.");
3096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
3097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Now allocate the JSObject on the heap by moving the new space allocation
3099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // top forward.
3100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // edi: constructor
3101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ebx: initial map
3102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset));
3103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ shl(ecx, kPointerSizeLog2);
3104592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ AllocateInNewSpace(ecx, edx, ecx, no_reg,
3105592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                        &generic_stub_call, NO_ALLOCATION_FLAGS);
3106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocated the JSObject, now initialize the fields and add the heap tag.
3108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ebx: initial map
3109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // edx: JSObject (untagged)
3110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(Operand(edx, JSObject::kMapOffset), ebx);
311144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(ebx, factory()->empty_fixed_array());
3112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(Operand(edx, JSObject::kPropertiesOffset), ebx);
3113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(Operand(edx, JSObject::kElementsOffset), ebx);
3114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Push the allocated object to the stack. This is the object that will be
3116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // returned (after it is tagged).
3117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(edx);
3118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // eax: argc
3120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // edx: JSObject (untagged)
3121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the address of the first in-object property into edx.
3122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ lea(edx, Operand(edx, JSObject::kHeaderSize));
3123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate the location of the first argument. The stack contains the
3124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // allocated object and the return address on top of the argc arguments.
3125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ lea(ecx, Operand(esp, eax, times_4, 1 * kPointerSize));
3126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use edi for holding undefined which is used in several places below.
312844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(edi, factory()->undefined_value());
3129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // eax: argc
3131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ecx: first argument
3132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // edx: first in-object property of the JSObject
3133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // edi: undefined
3134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill the initialized properties with a constant value or a passed argument
3135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // depending on the this.x = ...; assignment in the function.
3136592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Handle<SharedFunctionInfo> shared(function->shared());
3137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < shared->this_property_assignments_count(); i++) {
3138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (shared->IsThisPropertyAssignmentArgument(i)) {
3139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Check if the argument assigned to the property is actually passed.
3140e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // If argument is not passed the property is set to undefined,
3141e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // otherwise find it on the stack.
3142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int arg_number = shared->GetThisPropertyAssignmentArgument(i);
3143e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ mov(ebx, edi);
3144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ cmp(eax, arg_number);
31458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (CpuFeatures::IsSupported(CMOV)) {
3146e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        CpuFeatures::Scope use_cmov(CMOV);
3147e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ cmov(above, ebx, Operand(ecx, arg_number * -kPointerSize));
3148e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
3149e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        Label not_passed;
3150e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ j(below_equal, &not_passed);
3151e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ mov(ebx, Operand(ecx, arg_number * -kPointerSize));
3152e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ bind(&not_passed);
3153e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3154e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Store value in the property.
3155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ mov(Operand(edx, i * kPointerSize), ebx);
3156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
3157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Set the property to the constant value.
3158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i));
3159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ mov(Operand(edx, i * kPointerSize), Immediate(constant));
3160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
3161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill the unused in-object property fields with undefined.
31648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ASSERT(function->has_initial_map());
3165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = shared->this_property_assignments_count();
31668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang       i < function->initial_map()->inobject_properties();
3167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       i++) {
3168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(Operand(edx, i * kPointerSize), edi);
3169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move argc to ebx and retrieve and tag the JSObject to return.
3172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(ebx, eax);
3173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(eax);
3174592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ or_(eax, Immediate(kHeapObjectTag));
3175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Remove caller arguments and receiver from the stack and return.
3177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(ecx);
3178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ lea(esp, Operand(esp, ebx, times_pointer_size, 1 * kPointerSize));
3179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ecx);
318044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
318144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->constructed_objects(), 1);
318244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->constructed_objects_stub(), 1);
3183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
3184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the generic stub in case the specialized code cannot handle the
3186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // construction.
3187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&generic_stub_call);
3188592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Handle<Code> code = isolate()->builtins()->JSConstructStubGeneric();
3189592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ jmp(code, RelocInfo::CODE_TARGET);
3190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
3192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode();
3193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
31963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#undef __
31973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#define __ ACCESS_MASM(masm)
31983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
31993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
32003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
32013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MacroAssembler* masm) {
32021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ----------- S t a t e -------------
32031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- eax    : key
32041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- edx    : receiver
32051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- esp[0] : return address
32061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
32073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label slow, miss_force_generic;
3208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
32093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
32103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // have been verified by the caller to not be a smi.
32113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(eax, &miss_force_generic);
32123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(ebx, eax);
32133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SmiUntag(ebx);
32143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
32151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
32163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Push receiver on the stack to free up a register for the dictionary
32173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // probing.
32183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ push(edx);
32193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ LoadFromNumberDictionary(&slow,
32203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              ecx,
32213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              eax,
32223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              ebx,
32233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              edx,
32243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              edi,
32253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              eax);
32263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Pop receiver before returning.
32273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ pop(edx);
32283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ret(0);
3229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
32303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&slow);
32313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ pop(edx);
3232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- eax    : value
3235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ecx    : key
3236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- edx    : receiver
3237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- esp[0] : return address
3238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
32403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> slow_ic =
32413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_Slow();
32423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(slow_ic, RelocInfo::CODE_TARGET);
3243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
32443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&miss_force_generic);
32453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ----------- S t a t e -------------
32463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- eax    : value
32473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- ecx    : key
32483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- edx    : receiver
32493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- esp[0] : return address
32503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
3251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
32523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> miss_force_generic_ic =
32533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
32543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(miss_force_generic_ic, RelocInfo::CODE_TARGET);
32553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
3256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadExternalArray(
3259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    MacroAssembler* masm,
3260589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    ElementsKind elements_kind) {
3261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- eax    : key
3263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- edx    : receiver
3264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- esp[0] : return address
3265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss_force_generic, failed_allocation, slow;
3267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
3269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
32701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
32711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the key is a smi.
32723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(eax, &miss_force_generic);
32731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
32741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the index is in range.
3275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
327669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ cmp(eax, FieldOperand(ebx, ExternalArray::kLengthOffset));
32771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Unsigned comparison catches both negative and too-large values.
3278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(above_equal, &miss_force_generic);
32791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset));
32801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ebx: base pointer of external storage
32813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  switch (elements_kind) {
3282589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_BYTE_ELEMENTS:
328369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ SmiUntag(eax);  // Untag the index.
328469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ movsx_b(eax, Operand(ebx, eax, times_1, 0));
32851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3286589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3287589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_PIXEL_ELEMENTS:
328869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ SmiUntag(eax);  // Untag the index.
328969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ movzx_b(eax, Operand(ebx, eax, times_1, 0));
32901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3291589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_SHORT_ELEMENTS:
329269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ movsx_w(eax, Operand(ebx, eax, times_1, 0));
32931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3294589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
329569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ movzx_w(eax, Operand(ebx, eax, times_1, 0));
32961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3297589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
3298589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_INT_ELEMENTS:
329969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ mov(ecx, Operand(ebx, eax, times_2, 0));
33001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3301589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_FLOAT_ELEMENTS:
330269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ fld_s(Operand(ebx, eax, times_2, 0));
33031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3304589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_DOUBLE_ELEMENTS:
330569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ fld_d(Operand(ebx, eax, times_4, 0));
3306257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
33071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    default:
33081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      UNREACHABLE();
33091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
33101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
33111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // For integer array types:
33131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ecx: value
33141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // For floating-point array type:
33151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // FP(0): value
33161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3317589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (elements_kind == EXTERNAL_INT_ELEMENTS ||
3318589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) {
33191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // For the Int and UnsignedInt array types, we need to see whether
33201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // the value can be represented in a Smi. If not, we need to convert
33211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // it to a HeapNumber.
33221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Label box_int;
3323589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (elements_kind == EXTERNAL_INT_ELEMENTS) {
33241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ cmp(ecx, 0xC0000000);
33251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ j(sign, &box_int);
33261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    } else {
3327589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind);
33281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // The test is different for unsigned int values. Since we need
33291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // the value to be in the range of a positive smi, we can't
33301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // handle either of the top two bits being set in the value.
33311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ test(ecx, Immediate(0xC0000000));
33321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ j(not_zero, &box_int);
33331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
33341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ mov(eax, ecx);
33361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ SmiTag(eax);
33371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ ret(0);
33381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ bind(&box_int);
33401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Allocate a HeapNumber for the int and perform int-to-double
33421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // conversion.
3343589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (elements_kind == EXTERNAL_INT_ELEMENTS) {
33441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ push(ecx);
33451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ fild_s(Operand(esp, 0));
33461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ pop(ecx);
33471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    } else {
3348589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind);
33491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Need to zero-extend the value.
33501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // There's no fild variant for unsigned values, so zero-extend
33511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // to a 64-bit int manually.
33521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ push(Immediate(0));
33531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ push(ecx);
33541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ fild_d(Operand(esp, 0));
33551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ pop(ecx);
33561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ pop(ecx);
33571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
33581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // FP(0): value
33591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation);
33601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Set the value.
33611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ mov(eax, ecx);
33621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
33631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ ret(0);
3364589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
3365589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch             elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
33661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // For the floating-point array type, we need to always allocate a
33671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // HeapNumber.
33681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation);
33691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Set the value.
33701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ mov(eax, ecx);
33711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
33721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ ret(0);
33731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
33741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ SmiTag(eax);
33751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ ret(0);
33761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
33771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // If we fail allocation of the HeapNumber, we still have a value on
33791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // top of the FPU stack. Remove it.
33801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&failed_allocation);
3381592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ fstp(0);
33821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Fall through to slow case.
33831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Slow case: Jump to runtime.
33851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&slow);
3386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Counters* counters = masm->isolate()->counters();
338744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_external_array_slow(), 1);
3388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
33891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ----------- S t a t e -------------
33901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- eax    : key
33911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- edx    : receiver
33921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- esp[0] : return address
33931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
33941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Slow();
3396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(ic, RelocInfo::CODE_TARGET);
33971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- eax    : key
3400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- edx    : receiver
3401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- esp[0] : return address
3402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
34031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Miss case: Jump to runtime.
3405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
3406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> miss_ic =
3407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
34091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
34101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreExternalArray(
3413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    MacroAssembler* masm,
3414589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    ElementsKind elements_kind) {
34151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ----------- S t a t e -------------
3416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- eax    : key
34171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- edx    : receiver
34181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- esp[0] : return address
34191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
3420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss_force_generic, slow, check_heap_number;
342144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
3423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
342444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
34251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the key is a smi.
34263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(ecx, &miss_force_generic);
34271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the index is in range.
342944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
343069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ cmp(ecx, FieldOperand(edi, ExternalArray::kLengthOffset));
34311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Unsigned comparison catches both negative and too-large values.
34321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ j(above_equal, &slow);
34331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Handle both smis and HeapNumbers in the fast path. Go to the
34351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // runtime for all other kinds of values.
34361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // eax: value
34371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // edx: receiver
34381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ecx: key
34391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // edi: elements array
3440589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) {
34413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfNotSmi(eax, &slow);
34423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
34433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfNotSmi(eax, &check_heap_number);
34443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
344544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
34461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // smi case
344769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ mov(ebx, eax);  // Preserve the value in eax as the return value.
344869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ SmiUntag(ebx);
34491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
345069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // edi: base pointer of external storage
34513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  switch (elements_kind) {
3452589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_PIXEL_ELEMENTS:
345369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ ClampUint8(ebx);
345469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ SmiUntag(ecx);
345569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ mov_b(Operand(edi, ecx, times_1, 0), ebx);
345644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      break;
3457589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_BYTE_ELEMENTS:
3458589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
345969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ SmiUntag(ecx);
346069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ mov_b(Operand(edi, ecx, times_1, 0), ebx);
34611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3462589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_SHORT_ELEMENTS:
3463589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
346469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ mov_w(Operand(edi, ecx, times_1, 0), ebx);
34651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3466589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_INT_ELEMENTS:
3467589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
346869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ mov(Operand(edi, ecx, times_2, 0), ebx);
34691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3470589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_FLOAT_ELEMENTS:
3471589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_DOUBLE_ELEMENTS:
34721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Need to perform int-to-float conversion.
347369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ push(ebx);
34741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ fild_s(Operand(esp, 0));
347569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ pop(ebx);
3476589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
347769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ fstp_s(Operand(edi, ecx, times_2, 0));
3478589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      } else {  // elements_kind == EXTERNAL_DOUBLE_ELEMENTS.
347969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ fstp_d(Operand(edi, ecx, times_4, 0));
3480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
34811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
34821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    default:
34831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      UNREACHABLE();
34841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
34851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
34861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ ret(0);  // Return the original value.
34871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
348844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // TODO(danno): handle heap number -> pixel array conversion
3489589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) {
349044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ bind(&check_heap_number);
349144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // eax: value
349244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // edx: receiver
349344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // ecx: key
349444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // edi: elements array
349544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
3496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch           Immediate(masm->isolate()->factory()->heap_number_map()));
349744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ j(not_equal, &slow);
349844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
349944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // The WebGL specification leaves the behavior of storing NaN and
350044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // +/-Infinity into integer arrays basically undefined. For more
350144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // reproducible behavior, convert these to zero.
350244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
350344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // edi: base pointer of external storage
3504589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
350544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
350669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ fstp_s(Operand(edi, ecx, times_2, 0));
350744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ ret(0);
3508589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
3509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
351069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ fstp_d(Operand(edi, ecx, times_4, 0));
3511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ ret(0);
351244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else {
351344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Perform float-to-int conversion with truncation (round-to-zero)
351444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // behavior.
351544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
351644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // For the moment we make the slow call to the runtime on
351744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // processors that don't support SSE2. The code in IntegerConvert
351844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // (code-stubs-ia32.cc) is roughly what is needed here though the
351944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // conversion failure case does not need to be handled.
35208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (CpuFeatures::IsSupported(SSE2)) {
3521589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        if (elements_kind != EXTERNAL_INT_ELEMENTS &&
3522589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            elements_kind != EXTERNAL_UNSIGNED_INT_ELEMENTS) {
35238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          ASSERT(CpuFeatures::IsSupported(SSE2));
35241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          CpuFeatures::Scope scope(SSE2);
352569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          __ cvttsd2si(ebx, FieldOperand(eax, HeapNumber::kValueOffset));
352644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          // ecx: untagged integer value
35273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          switch (elements_kind) {
3528589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            case EXTERNAL_PIXEL_ELEMENTS:
352969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              __ ClampUint8(ebx);
353069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              // Fall through.
3531589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            case EXTERNAL_BYTE_ELEMENTS:
3532589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
353369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              __ SmiUntag(ecx);
353469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              __ mov_b(Operand(edi, ecx, times_1, 0), ebx);
353544f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
3536589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            case EXTERNAL_SHORT_ELEMENTS:
3537589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
353869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              __ mov_w(Operand(edi, ecx, times_1, 0), ebx);
353944f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
354044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            default:
354144f0eee88ff00398ff7f715fab053374d808c90dSteve Block              UNREACHABLE();
354244f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
354344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          }
354444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
35458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          if (CpuFeatures::IsSupported(SSE3)) {
354644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            CpuFeatures::Scope scope(SSE3);
354744f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // fisttp stores values as signed integers. To represent the
354844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // entire range of int and unsigned int arrays, store as a
354944f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // 64-bit int and discard the high 32 bits.
355044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // If the value is NaN or +/-infinity, the result is 0x80000000,
355144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // which is automatically zero when taken mod 2^n, n < 32.
355244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
3553592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch            __ sub(esp, Immediate(2 * kPointerSize));
355444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            __ fisttp_d(Operand(esp, 0));
355569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            __ pop(ebx);
3556592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch            __ add(esp, Immediate(kPointerSize));
355744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else {
35588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            ASSERT(CpuFeatures::IsSupported(SSE2));
355944f0eee88ff00398ff7f715fab053374d808c90dSteve Block            CpuFeatures::Scope scope(SSE2);
356044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // We can easily implement the correct rounding behavior for the
356144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // range [0, 2^31-1]. For the time being, to keep this code simple,
356244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // make the slow runtime call for values outside this range.
356344f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // Note: we could do better for signed int arrays.
356444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            __ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset));
356544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // We will need the key if we have to make the slow runtime call.
356669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            __ push(ebx);
356769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            __ LoadPowerOf2(xmm1, ebx, 31);
356869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            __ pop(ebx);
356944f0eee88ff00398ff7f715fab053374d808c90dSteve Block            __ ucomisd(xmm1, xmm0);
357044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            __ j(above_equal, &slow);
357169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            __ cvttsd2si(ebx, Operand(xmm0));
357244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          }
357369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          // ebx: untagged integer value
357469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          __ mov(Operand(edi, ecx, times_2, 0), ebx);
35751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        }
357644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ ret(0);  // Return original value.
35771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
35781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
35791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
35801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Slow case: call runtime.
35821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&slow);
3583257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Counters* counters = masm->isolate()->counters();
3584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->keyed_store_external_array_slow(), 1);
3585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
35861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ----------- S t a t e -------------
35871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- eax    : value
35881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- ecx    : key
35891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- edx    : receiver
35901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- esp[0] : return address
35911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
35921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow();
3594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(ic, RelocInfo::CODE_TARGET);
3595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- eax    : value
3598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ecx    : key
3599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- edx    : receiver
3600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- esp[0] : return address
3601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
3604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> miss_ic =
3605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
3611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- eax    : key
3613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- edx    : receiver
3614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- esp[0] : return address
3615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss_force_generic;
3617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
3619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
3620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3621257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is a smi.
36223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(eax, &miss_force_generic);
3623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the elements array.
3625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
3626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ AssertFastElements(ecx);
3627257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is within bounds.
3629257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset));
3630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(above_equal, &miss_force_generic);
3631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the result and make sure it's not the hole.
3633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(ebx, Operand(ecx, eax, times_2,
3634257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      FixedArray::kHeaderSize - kHeapObjectTag));
3635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ cmp(ebx, masm->isolate()->factory()->the_hole_value());
3636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(equal, &miss_force_generic);
3637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(eax, ebx);
3638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ret(0);
3639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
3641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> miss_ic =
3642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
36473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(
36483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MacroAssembler* masm) {
36493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ----------- S t a t e -------------
36503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- eax    : key
36513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- edx    : receiver
36523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- esp[0] : return address
36533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
36543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label miss_force_generic, slow_allocate_heapnumber;
36553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
36563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
36573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // have been verified by the caller to not be a smi.
36583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
36593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is a smi.
36603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(eax, &miss_force_generic);
36613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
36623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Get the elements array.
36633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
36643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ AssertFastElements(ecx);
36653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
36663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is within bounds.
36673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmp(eax, FieldOperand(ecx, FixedDoubleArray::kLengthOffset));
36683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(above_equal, &miss_force_generic);
36693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
36703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check for the hole
36713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
36723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmp(FieldOperand(ecx, eax, times_4, offset), Immediate(kHoleNanUpper32));
36733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(equal, &miss_force_generic);
36743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
36753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Always allocate a heap number for the result.
36763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (CpuFeatures::IsSupported(SSE2)) {
36773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    CpuFeatures::Scope use_sse2(SSE2);
36783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ movdbl(xmm0, FieldOperand(ecx, eax, times_4,
36793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                 FixedDoubleArray::kHeaderSize));
36803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
36813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ fld_d(FieldOperand(ecx, eax, times_4, FixedDoubleArray::kHeaderSize));
36823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
36833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ AllocateHeapNumber(ecx, ebx, edi, &slow_allocate_heapnumber);
36843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Set the value.
36853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (CpuFeatures::IsSupported(SSE2)) {
36863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    CpuFeatures::Scope use_sse2(SSE2);
36873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ movdbl(FieldOperand(ecx, HeapNumber::kValueOffset), xmm0);
36883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
36893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ fstp_d(FieldOperand(ecx, HeapNumber::kValueOffset));
36903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
36913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(eax, ecx);
36923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ret(0);
36933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
36943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&slow_allocate_heapnumber);
36953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // A value was pushed on the floating point stack before the allocation, if
36963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // the allocation fails it needs to be removed.
36973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (!CpuFeatures::IsSupported(SSE2)) {
3698592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ fstp(0);
36993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
37003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> slow_ic =
37013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_Slow();
37023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(slow_ic, RelocInfo::CODE_TARGET);
37033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&miss_force_generic);
37053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> miss_ic =
37063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
37073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
37083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
37093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3711592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastElement(
3712592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    MacroAssembler* masm,
3713592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    bool is_js_array,
3714592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    ElementsKind elements_kind) {
3715257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
37163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- eax    : value
37173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- ecx    : key
3718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- edx    : receiver
3719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- esp[0] : return address
3720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3721592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Label miss_force_generic, transition_elements_kind;
3722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
3724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
3725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is a smi.
37273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(ecx, &miss_force_generic);
37281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the elements array and make sure it is a fast element array, not 'cow'.
3730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
3731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ cmp(FieldOperand(edi, HeapObject::kMapOffset),
3732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         Immediate(masm->isolate()->factory()->fixed_array_map()));
3733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss_force_generic);
3734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (is_js_array) {
3736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check that the key is within bounds.
3737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset));  // smis.
3738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(above_equal, &miss_force_generic);
3739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
3740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check that the key is within bounds.
3741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset));  // smis.
3742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(above_equal, &miss_force_generic);
3743257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3744257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3745592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
3746592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ JumpIfNotSmi(eax, &transition_elements_kind);
3747592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // ecx is a smi, use times_half_pointer_size instead of
3748592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // times_pointer_size
3749592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(FieldOperand(edi,
3750592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                        ecx,
3751592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                        times_half_pointer_size,
3752592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                        FixedArray::kHeaderSize), eax);
3753592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  } else {
3754592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    ASSERT(elements_kind == FAST_ELEMENTS);
3755592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Do the store and update the write barrier.
3756592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // ecx is a smi, use times_half_pointer_size instead of
3757592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // times_pointer_size
3758592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ lea(ecx, FieldOperand(edi,
3759592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                             ecx,
3760592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                             times_half_pointer_size,
3761592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                             FixedArray::kHeaderSize));
3762592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(Operand(ecx, 0), eax);
3763592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Make sure to preserve the value in register eax.
3764592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(edx, eax);
3765592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ RecordWrite(edi, ecx, edx, kDontSaveFPRegs);
3766592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
3767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Done.
3769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ret(0);
37701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Handle store cache miss, replacing the ic with the generic stub.
3772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
3773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic_force_generic =
3774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
3776592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
3777592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Handle transition to other elements kinds without using the generic stub.
3778592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ bind(&transition_elements_kind);
3779592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
3780592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ jmp(ic_miss, RelocInfo::CODE_TARGET);
37811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
37821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
37831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
37843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
37853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MacroAssembler* masm,
37863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bool is_js_array) {
37873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ----------- S t a t e -------------
37883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- eax    : value
37893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- ecx    : key
37903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- edx    : receiver
37913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- esp[0] : return address
37923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
3793592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Label miss_force_generic, transition_elements_kind;
37943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
37963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // have been verified by the caller to not be a smi.
37973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is a smi.
37993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(ecx, &miss_force_generic);
38003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
38013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Get the elements array.
38023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
38033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ AssertFastElements(edi);
38043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
38053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (is_js_array) {
38063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Check that the key is within bounds.
38073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset));  // smis.
38083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
38093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Check that the key is within bounds.
38103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset));  // smis.
38113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
38123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(above_equal, &miss_force_generic);
38133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3814592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ StoreNumberToDoubleElements(eax,
3815592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                 edi,
3816592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                 ecx,
3817592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                 edx,
3818592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                 xmm0,
3819592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                 &transition_elements_kind,
3820592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                 true);
38213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ret(0);
38223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
38233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Handle store cache miss, replacing the ic with the generic stub.
38243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&miss_force_generic);
38253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> ic_force_generic =
38263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
38273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
3828592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
3829592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Handle transition to other elements kinds without using the generic stub.
3830592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ bind(&transition_elements_kind);
3831592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
3832592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ jmp(ic_miss, RelocInfo::CODE_TARGET);
38333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
38343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
38353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __
3837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
3839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
3840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_IA32
3841