13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 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,
473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       Register receiver,
483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       // Number of the cache entry pointer-size scaled.
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       Register offset,
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       Register extra) {
5144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference key_offset(isolate->stub_cache()->key_reference(table));
5244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference value_offset(isolate->stub_cache()->value_reference(table));
533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExternalReference map_offset(isolate->stub_cache()->map_reference(table));
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Multiply by 3 because there are 3 fields per entry (name, code, map).
583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lea(offset, Operand(offset, offset, times_2, 0));
593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (extra.is_valid()) {
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Get the code entry from the cache.
623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(extra, Operand::StaticArray(offset, times_1, value_offset));
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Check that the key in the entry matches the name.
653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(name, Operand::StaticArray(offset, times_1, key_offset));
663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &miss);
673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check the map matches.
693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(offset, Operand::StaticArray(offset, times_1, map_offset));
703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(offset, FieldOperand(receiver, HeapObject::kMapOffset));
71257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(not_equal, &miss);
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Check that the flags match what we're looking for.
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(offset, FieldOperand(extra, Code::kFlagsOffset));
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ and_(offset, ~Code::kFlagsNotUsedInLookup);
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(offset, flags);
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ j(not_equal, &miss);
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) {
813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(&miss);
823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) {
833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(&miss);
843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Jump to the first instruction in the code stub.
883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(extra, Immediate(Code::kHeaderSize - kHeapObjectTag));
893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(extra);
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&miss);
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Save the offset on the stack.
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ push(offset);
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Check that the key in the entry matches the name.
973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(name, Operand::StaticArray(offset, times_1, key_offset));
983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &miss);
993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check the map matches.
1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(offset, Operand::StaticArray(offset, times_1, map_offset));
1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(offset, FieldOperand(receiver, HeapObject::kMapOffset));
103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(not_equal, &miss);
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Restore offset register.
1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(offset, Operand(esp, 0));
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Get the code entry from the cache.
1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(offset, Operand::StaticArray(offset, times_1, value_offset));
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Check that the flags match what we're looking for.
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(offset, FieldOperand(offset, Code::kFlagsOffset));
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ and_(offset, ~Code::kFlagsNotUsedInLookup);
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(offset, flags);
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ j(not_equal, &miss);
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) {
1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(&miss);
1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) {
1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(&miss);
1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Restore offset and re-load code entry from cache.
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ pop(offset);
1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(offset, Operand::StaticArray(offset, times_1, value_offset));
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Jump to the first instruction in the code stub.
1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(offset, Immediate(Code::kHeaderSize - kHeapObjectTag));
1313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(offset);
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Pop at miss.
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&miss);
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ pop(offset);
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1408defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Helper function used to check that the dictionary doesn't contain
1418defd9ff6930b4e24729971a61cf7469daf119beSteve Block// the property. This function may return false negatives, so miss_label
1428defd9ff6930b4e24729971a61cf7469daf119beSteve Block// must always call a backup property check that is complete.
1438defd9ff6930b4e24729971a61cf7469daf119beSteve Block// This function is safe to call if the receiver has fast properties.
1448defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Name must be a symbol and receiver must be a heap object.
1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Label* miss_label,
1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Register receiver,
1483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Handle<String> name,
1493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Register r0,
1503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Register r1) {
1518defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ASSERT(name->IsSymbol());
15244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm->isolate()->counters();
15344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->negative_lookups(), 1);
15444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->negative_lookups_miss(), 1);
1558defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1568defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset));
1578defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1588defd9ff6930b4e24729971a61cf7469daf119beSteve Block  const int kInterceptorOrAccessCheckNeededMask =
1598defd9ff6930b4e24729971a61cf7469daf119beSteve Block      (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
1603bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
1618defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Bail out if the receiver has a named interceptor or requires access checks.
1623bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  __ test_b(FieldOperand(r0, Map::kBitFieldOffset),
1633bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch            kInterceptorOrAccessCheckNeededMask);
164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_zero, miss_label);
1658defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Check that receiver is a JSObject.
1673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CmpInstanceType(r0, FIRST_SPEC_OBJECT_TYPE);
168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(below, miss_label);
1698defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1708defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Load properties array.
1718defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Register properties = r0;
1728defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset));
1738defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1748defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Check that the properties array is a dictionary.
1758defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ cmp(FieldOperand(properties, HeapObject::kMapOffset),
17644f0eee88ff00398ff7f715fab053374d808c90dSteve Block         Immediate(masm->isolate()->factory()->hash_table_map()));
1778defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ j(not_equal, miss_label);
1788defd9ff6930b4e24729971a61cf7469daf119beSteve Block
179257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringDictionaryLookupStub::GenerateNegativeLookup(masm,
1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     miss_label,
1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     &done,
1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     properties,
1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     name,
1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     r1);
1868defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ bind(&done);
18744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->negative_lookups_miss(), 1);
1888defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
1898defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1908defd9ff6930b4e24729971a61cf7469daf119beSteve Block
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCache::GenerateProbe(MacroAssembler* masm,
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Code::Flags flags,
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Register receiver,
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Register name,
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Register scratch,
1963e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                              Register extra,
1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Register extra2,
1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Register extra3) {
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Assert that code is valid.  The multiplying code relies on the entry size
2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // being 12.
2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(sizeof(Entry) == 12);
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Assert the flags do not name a specific type.
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Assert that there are no register conflicts.
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!scratch.is(receiver));
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!scratch.is(name));
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!extra.is(receiver));
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!extra.is(name));
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!extra.is(scratch));
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Assert scratch and extra registers are valid, and extra2/3 are unused.
2163e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(!scratch.is(no_reg));
2173e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ASSERT(extra2.is(no_reg));
2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(extra3.is(no_reg));
2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register offset = scratch;
2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  scratch = no_reg;
2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Counters* counters = masm->isolate()->counters();
2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1);
2253e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
2273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver, &miss);
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the map of the receiver and compute the hash.
2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(offset, FieldOperand(name, String::kHashFieldOffset));
2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(offset, FieldOperand(receiver, HeapObject::kMapOffset));
2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ xor_(offset, flags);
2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We mask out the last two bits because they are not part of the hash and
2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // they are always 01 for maps.  Also in the two 'and' instructions below.
2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ and_(offset, (kPrimaryTableSize - 1) << kHeapObjectTagSize);
2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ProbeTable expects the offset to be pointer scaled, which it is, because
2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the heap object tag size is 2 and the pointer size log 2 is also 2.
2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(kHeapObjectTagSize == kPointerSizeLog2);
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Probe the primary table.
2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ProbeTable(isolate(), masm, flags, kPrimary, name, receiver, offset, extra);
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Primary miss: Compute hash for secondary probe.
2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(offset, FieldOperand(name, String::kHashFieldOffset));
2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(offset, FieldOperand(receiver, HeapObject::kMapOffset));
2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ xor_(offset, flags);
2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ and_(offset, (kPrimaryTableSize - 1) << kHeapObjectTagSize);
2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sub(offset, name);
2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(offset, Immediate(flags));
2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ and_(offset, (kSecondaryTableSize - 1) << kHeapObjectTagSize);
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Probe the secondary table.
2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ProbeTable(
2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      isolate(), masm, flags, kSecondary, name, receiver, offset, extra);
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Cache miss: Fall-through and let caller handle the miss by
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // entering the runtime system.
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1);
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                       int index,
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                       Register prototype) {
26680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ LoadGlobalFunction(index, prototype);
26780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ LoadGlobalFunctionInitialMap(prototype, prototype);
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the prototype from the initial map.
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MacroAssembler* masm,
2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int index,
2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register prototype,
2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* miss) {
2780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Check we're still in the same context.
2790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ cmp(Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)),
28044f0eee88ff00398ff7f715fab053374d808c90dSteve Block         masm->isolate()->global());
2810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ j(not_equal, miss);
2827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Get the global function with the given index.
2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSFunction> function(
2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      JSFunction::cast(masm->isolate()->global_context()->get(index)));
2857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Load its initial map. The global functions all have initial maps.
2867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ Set(prototype, Immediate(Handle<Map>(function->initial_map())));
2877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Load the prototype from the initial map.
2887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
2897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register receiver,
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register scratch,
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Label* miss_label) {
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
2973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver, miss_label);
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object is a JS array.
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, miss_label);
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load length directly from the JS array.
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset));
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate code to check if an object is a string.  If the object is
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// a string, the map's instance type is left in the scratch register.
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GenerateStringCheck(MacroAssembler* masm,
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Register receiver,
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Register scratch,
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Label* smi,
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                Label* non_string_object) {
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object isn't a smi.
3173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver, smi);
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object is a string.
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
32269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kNotStringTag != 0);
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ test(scratch, Immediate(kNotStringTag));
324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_zero, non_string_object);
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Register receiver,
330402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                            Register scratch1,
331402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                            Register scratch2,
3321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                            Label* miss,
3331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                            bool support_wrappers) {
334402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Label check_wrapper;
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if the object is a string leaving the instance type in the
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch register.
3381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  GenerateStringCheck(masm, receiver, scratch1, miss,
3391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                      support_wrappers ? &check_wrapper : miss);
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
341d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Load length from the string and convert to a smi.
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(eax, FieldOperand(receiver, String::kLengthOffset));
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (support_wrappers) {
3461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Check if the object is a JSValue wrapper.
3471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ bind(&check_wrapper);
3481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ cmp(scratch1, JS_VALUE_TYPE);
349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(not_equal, miss);
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Check if the wrapped value is a string and load the length
3521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // directly if it is.
3531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset));
3541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    GenerateStringCheck(masm, scratch2, scratch1, miss, miss);
3551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ mov(eax, FieldOperand(scratch2, String::kLengthOffset));
3561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ ret(0);
3571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 Register receiver,
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 Register scratch1,
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 Register scratch2,
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 Label* miss_label) {
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(eax, scratch1);
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Load a fast property out of a holder object (src). In-object properties
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// are loaded directly otherwise the property is loaded from the properties
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// fixed array.
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            Register dst,
3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            Register src,
3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            Handle<JSObject> holder,
3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            int index) {
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adjust for the number of properties stored in the holder.
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  index -= holder->map()->inobject_properties();
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (index < 0) {
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Get the property straight out of the holder.
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = holder->map()->instance_size() + (index * kPointerSize);
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(dst, FieldOperand(src, offset));
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Calculate the offset into the properties array.
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = index * kPointerSize + FixedArray::kHeaderSize;
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset));
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(dst, FieldOperand(dst, offset));
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
395402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescustatic void PushInterceptorArguments(MacroAssembler* masm,
396402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                     Register receiver,
397402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                     Register holder,
398402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                     Register name,
3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Handle<JSObject> holder_obj) {
400402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(name);
4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor());
4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor));
4036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register scratch = name;
4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(scratch, Immediate(interceptor));
4056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(scratch);
406402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(receiver);
4076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(holder);
4086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(FieldOperand(scratch, InterceptorInfo::kDataOffset));
409402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
410402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
411402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void CompileCallLoadPropertyWithInterceptor(
4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MacroAssembler* masm,
4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register receiver,
4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register holder,
4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register name,
4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder_obj) {
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
419402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ CallExternalReference(
42044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly),
42144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        masm->isolate()),
42244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      5);
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
42690bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner// Number of pointers to be reserved on stack for fast API call.
42790bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brennerstatic const int kFastApiCallArguments = 3;
42890bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner
42990bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner
4308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang// Reserves space for the extra arguments to API function in the
431402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// caller's frame.
432402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu//
433402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// These arguments are set by CheckPrototypes and GenerateFastApiCall.
434402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescustatic void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
435402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // ----------- S t a t e -------------
436402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- esp[0] : return address
437402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- esp[4] : last argument in the internal frame of the caller
438402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // -----------------------------------
439402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ pop(scratch);
44090bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  for (int i = 0; i < kFastApiCallArguments; i++) {
44190bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner    __ push(Immediate(Smi::FromInt(0)));
44290bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  }
443402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(scratch);
444402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
445402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
446402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
447402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// Undoes the effects of ReserveSpaceForFastApiCall.
448402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescustatic void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
449402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // ----------- S t a t e -------------
45090bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  //  -- esp[0]  : return address.
45190bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  //  -- esp[4]  : last fast api call extra argument.
452402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- ...
45390bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  //  -- esp[kFastApiCallArguments * 4] : first fast api call extra argument.
45490bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  //  -- esp[kFastApiCallArguments * 4 + 4] : last argument in the internal
45590bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  //                                          frame.
456402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // -----------------------------------
457402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ pop(scratch);
4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(esp, Immediate(kPointerSize * kFastApiCallArguments));
459402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(scratch);
460402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
461402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
462402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
4638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang// Generates call to API function.
4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateFastApiCall(MacroAssembler* masm,
4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                const CallOptimization& optimization,
4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                int argc) {
467402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // ----------- S t a t e -------------
468402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- esp[0]              : return address
469402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- esp[4]              : object passing the type check
470402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //                           (last fast api call extra argument,
471402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //                            set by CheckPrototypes)
47290bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  //  -- esp[8]              : api function
473402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //                           (first fast api call extra argument)
47490bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  //  -- esp[12]             : api call data
47590bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  //  -- esp[16]             : last argument
476402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- ...
47790bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  //  -- esp[(argc + 3) * 4] : first argument
47890bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  //  -- esp[(argc + 4) * 4] : receiver
479402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // -----------------------------------
480402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Get the function and setup the context.
4813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSFunction> function = optimization.constant_function();
4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadHeapObject(edi, function);
483402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
484402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
4858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Pass the additional arguments.
48690bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  __ mov(Operand(esp, 2 * kPointerSize), edi);
4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Object> call_data(api_call_info->data());
4893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (masm->isolate()->heap()->InNewSpace(*call_data)) {
4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(ecx, api_call_info);
491402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset));
49290bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner    __ mov(Operand(esp, 3 * kPointerSize), ebx);
493402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  } else {
4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(Operand(esp, 3 * kPointerSize), Immediate(call_data));
495402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
496402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
4978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Prepare arguments.
49890bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  __ lea(eax, Operand(esp, 3 * kPointerSize));
499402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
5008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const int kApiArgc = 1;  // API function gets reference to the v8::Arguments.
50190bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner
5028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Allocate the v8::Arguments structure in the arguments' space since
5038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // it's not controlled by GC.
5048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const int kApiStackSpace = 4;
5058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ PrepareCallApiFunction(kApiArgc + kApiStackSpace);
5078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(ApiParameterOperand(1), eax);  // v8::Arguments::implicit_args_.
5093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(eax, Immediate(argc * kPointerSize));
5108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(ApiParameterOperand(2), eax);  // v8::Arguments::values_.
5118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Set(ApiParameterOperand(3), Immediate(argc));  // v8::Arguments::length_.
5128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // v8::Arguments::is_construct_call_.
5138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Set(ApiParameterOperand(4), Immediate(0));
5148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // v8::InvocationCallback's argument.
5168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ lea(eax, ApiParameterOperand(1));
5178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(ApiParameterOperand(0), eax);
51890bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner
5193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Function address is a foreign pointer outside V8's heap.
5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address function_address = v8::ToCData<Address>(api_call_info->callback());
5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallApiFunctionAndReturn(function_address,
5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              argc + kFastApiCallArguments + 1);
523402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
524402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
525402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CallInterceptorCompiler BASE_EMBEDDED {
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
528402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CallInterceptorCompiler(StubCompiler* stub_compiler,
529402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                          const ParameterCount& arguments,
530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          Register name,
5313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          Code::ExtraICState extra_state)
532402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      : stub_compiler_(stub_compiler),
533402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        arguments_(arguments),
534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        name_(name),
5353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        extra_state_(extra_state) {}
5363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Compile(MacroAssembler* masm,
5383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Handle<JSObject> object,
5393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Handle<JSObject> holder,
5403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Handle<String> name,
5413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               LookupResult* lookup,
5423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Register receiver,
5433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Register scratch1,
5443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Register scratch2,
5453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Register scratch3,
5463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               Label* miss) {
547402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    ASSERT(holder->HasNamedInterceptor());
548402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
549402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
550402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Check that the receiver isn't a smi.
5513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(receiver, miss);
552402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
553402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    CallOptimization optimization(lookup);
5546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (optimization.is_constant_call()) {
5553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3,
5563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       holder, lookup, name, optimization, miss);
557402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    } else {
5583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3,
5593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     name, holder, miss);
560402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    }
561402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
563402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu private:
5643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CompileCacheable(MacroAssembler* masm,
5653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Handle<JSObject> object,
5663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Register receiver,
5673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Register scratch1,
5683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Register scratch2,
5693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Register scratch3,
5703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Handle<JSObject> interceptor_holder,
5713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        LookupResult* lookup,
5723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Handle<String> name,
5733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        const CallOptimization& optimization,
5743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Label* miss_label) {
575402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    ASSERT(optimization.is_constant_call());
576402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    ASSERT(!lookup->holder()->IsGlobalObject());
577402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
578402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    int depth1 = kInvalidProtoDepth;
579402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    int depth2 = kInvalidProtoDepth;
580402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    bool can_do_fast_api_call = false;
581402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    if (optimization.is_simple_api_call() &&
582402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        !lookup->holder()->IsGlobalObject()) {
5833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      depth1 = optimization.GetPrototypeDepthOfExpectedType(
5843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          object, interceptor_holder);
585402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      if (depth1 == kInvalidProtoDepth) {
5863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        depth2 = optimization.GetPrototypeDepthOfExpectedType(
5873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            interceptor_holder, Handle<JSObject>(lookup->holder()));
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
5893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      can_do_fast_api_call =
5903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth;
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
59344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Counters* counters = masm->isolate()->counters();
59444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ IncrementCounter(counters->call_const_interceptor(), 1);
595402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
596402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    if (can_do_fast_api_call) {
59744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1);
598402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      ReserveSpaceForFastApiCall(masm, scratch1);
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Check that the maps from receiver to interceptor's holder
602f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // haven't changed and thus we can invoke interceptor.
603402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Label miss_cleanup;
604402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
605402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Register holder =
6063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
6073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        scratch1, scratch2, scratch3,
6083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        name, depth1, miss);
609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
610f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Invoke an interceptor and if it provides a value,
611f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // branch to |regular_invoke|.
612402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Label regular_invoke;
613f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    LoadWithInterceptor(masm, receiver, holder, interceptor_holder,
614f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                        &regular_invoke);
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
616f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Interceptor returned nothing for this property.  Try to use cached
617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // constant function.
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
619f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Check that the maps from interceptor's holder to constant function's
620f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // holder haven't changed and thus we can use cached constant function.
6213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (*interceptor_holder != lookup->holder()) {
6227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      stub_compiler_->CheckPrototypes(interceptor_holder, receiver,
6233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Handle<JSObject>(lookup->holder()),
6243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      scratch1, scratch2, scratch3,
6253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      name, depth2, miss);
6267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    } else {
6277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // CheckPrototypes has a side effect of fetching a 'holder'
6287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // for API (object which is instanceof for the signature).  It's
6297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // safe to omit it here, as if present, it should be fetched
6307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // by the previous CheckPrototypes.
6317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ASSERT(depth2 == kInvalidProtoDepth);
6327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
634f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Invoke function.
635402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    if (can_do_fast_api_call) {
6363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GenerateFastApiCall(masm, optimization, arguments_.immediate());
637402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    } else {
6383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          ? CALL_AS_FUNCTION
640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          : CALL_AS_METHOD;
641402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ InvokeFunction(optimization.constant_function(), arguments_,
642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        JUMP_FUNCTION, NullCallWrapper(), call_kind);
643402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    }
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
645f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Deferred code for fast API call case---clean preallocated space.
646402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    if (can_do_fast_api_call) {
647402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ bind(&miss_cleanup);
648402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      FreeSpaceForFastApiCall(masm, scratch1);
649402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ jmp(miss_label);
650402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    }
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
652f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // Invoke a regular function.
653402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ bind(&regular_invoke);
654402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    if (can_do_fast_api_call) {
655402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      FreeSpaceForFastApiCall(masm, scratch1);
656402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    }
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void CompileRegular(MacroAssembler* masm,
6603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Handle<JSObject> object,
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Register receiver,
662402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                      Register scratch1,
663402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                      Register scratch2,
6643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                      Register scratch3,
6653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Handle<String> name,
6663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      Handle<JSObject> interceptor_holder,
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Label* miss_label) {
668402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    Register holder =
669f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
6703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        scratch1, scratch2, scratch3,
6713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        name, miss_label);
672402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
674e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Save the name_ register across the call.
675e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(name_);
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder);
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
679402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ CallExternalReference(
68044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall),
68144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          masm->isolate()),
68244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        5);
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
684e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Restore the name_ register.
685e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ pop(name_);
6863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Leave the internal frame.
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
690402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void LoadWithInterceptor(MacroAssembler* masm,
691402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                           Register receiver,
692402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                           Register holder,
6933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Handle<JSObject> holder_obj,
694402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                           Label* interceptor_succeeded) {
6953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    {
6963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FrameScope scope(masm, StackFrame::INTERNAL);
6973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ push(holder);  // Save the holder.
6983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ push(name_);  // Save the name.
6993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CompileCallLoadPropertyWithInterceptor(masm,
7013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             receiver,
7023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             holder,
7033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             name_,
7043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             holder_obj);
7053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(name_);  // Restore the name.
7073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(receiver);  // Restore the holder.
7083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Leave the internal frame.
7093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
710402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
71144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmp(eax, masm->isolate()->factory()->no_interceptor_result_sentinel());
712402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ j(not_equal, interceptor_succeeded);
713402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
714402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
715402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  StubCompiler* stub_compiler_;
716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const ParameterCount& arguments_;
717e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Register name_;
7183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Code::ExtraICState extra_state_;
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
7243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> code = (kind == Code::LOAD_IC)
7253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ? masm->isolate()->builtins()->LoadIC_Miss()
7263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : masm->isolate()->builtins()->KeyedLoadIC_Miss();
7273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(code, RelocInfo::CODE_TARGET);
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) {
7323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> code =
7333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
7343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(code, RelocInfo::CODE_TARGET);
735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
738402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// Both name_reg and receiver_reg are preserved on jumps to miss_label,
739402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// but may be destroyed if store is successful.
740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateStoreField(MacroAssembler* masm,
7413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Handle<JSObject> object,
742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      int index,
7433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Handle<Map> transition,
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register receiver_reg,
745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register name_reg,
746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register scratch,
747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Label* miss_label) {
748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the object hasn't changed.
7498f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS
7508f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch                                             : REQUIRE_EXACT_MAP;
7513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(receiver_reg, Handle<Map>(object->map()),
7528f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch              miss_label, DO_SMI_CHECK, mode);
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform global security token check if needed.
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsJSGlobalProxy()) {
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub never generated for non-global objects that require access
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // checks.
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform map transition for the receiver if necessary.
7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) {
765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The properties must be extended before we can store the value.
766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // We jump to a runtime call that extends the properties array.
767402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ pop(scratch);  // Return address.
768402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ push(receiver_reg);
7693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(Immediate(transition));
770402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ push(eax);
771402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ push(scratch);
7726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ TailCallExternalReference(
77344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
77444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          masm->isolate()),
77544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        3,
77644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        1);
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!transition.is_null()) {
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Update the map of the object; no write barrier updating is
782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // needed because the map is never in new space.
783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset),
7843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Immediate(transition));
785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adjust for the number of properties stored in the object. Even in the
788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // face of a transition we can use the old map here because the size of the
789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object and the number of in-object properties is not going to change.
790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  index -= object->map()->inobject_properties();
791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (index < 0) {
793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Set the property straight into the object.
794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = object->map()->instance_size() + (index * kPointerSize);
795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(FieldOperand(receiver_reg, offset), eax);
796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Update the write barrier for the array address.
798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Pass the value being stored in the now unused name_reg.
7993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(name_reg, eax);
8003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteField(receiver_reg,
8013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        offset,
8023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        name_reg,
8033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        scratch,
8043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        kDontSaveFPRegs);
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Write to the properties array.
807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = index * kPointerSize + FixedArray::kHeaderSize;
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Get the properties array (optimistically).
809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(FieldOperand(scratch, offset), eax);
811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Update the write barrier for the array address.
813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Pass the value being stored in the now unused name_reg.
8143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(name_reg, eax);
8153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteField(scratch,
8163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        offset,
8173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        name_reg,
8183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        receiver_reg,
8193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        kDontSaveFPRegs);
820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the value (register eax).
823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Generate code to check that a global property cell is empty. Create
8286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// the property cell at compilation time if no cell exists for the
8296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// property.
8303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateCheckPropertyCell(MacroAssembler* masm,
8313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Handle<GlobalObject> global,
8323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Handle<String> name,
8333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Register scratch,
8343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Label* miss) {
8353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSGlobalPropertyCell> cell =
8363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GlobalObject::EnsurePropertyCell(global, name);
8376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(cell->value()->IsTheHole());
8383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Oddball> the_hole = masm->isolate()->factory()->the_hole_value();
839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (Serializer::enabled()) {
8403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(scratch, Immediate(cell));
841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset),
8423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Immediate(the_hole));
843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
8443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(Operand::Cell(cell), Immediate(the_hole));
845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
846257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, miss);
8476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
8486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8508defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Calls GenerateCheckPropertyCell for each global object in the prototype chain
8518defd9ff6930b4e24729971a61cf7469daf119beSteve Block// from object to (but not including) holder.
8523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateCheckPropertyCells(MacroAssembler* masm,
8533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Handle<JSObject> object,
8543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Handle<JSObject> holder,
8553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Handle<String> name,
8563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Register scratch,
8573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Label* miss) {
8583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSObject> current = object;
8593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while (!current.is_identical_to(holder)) {
8608defd9ff6930b4e24729971a61cf7469daf119beSteve Block    if (current->IsGlobalObject()) {
8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GenerateCheckPropertyCell(masm,
8623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                Handle<GlobalObject>::cast(current),
8633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                name,
8643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                scratch,
8653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                miss);
8668defd9ff6930b4e24729971a61cf7469daf119beSteve Block    }
8673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    current = Handle<JSObject>(JSObject::cast(current->GetPrototype()));
8688defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
8698defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
8708defd9ff6930b4e24729971a61cf7469daf119beSteve Block
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm())
873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8753ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochRegister StubCompiler::CheckPrototypes(Handle<JSObject> object,
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       Register object_reg,
8773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Handle<JSObject> holder,
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       Register holder_reg,
8793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       Register scratch1,
8803bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       Register scratch2,
8813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Handle<String> name,
8828defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                       int save_at_depth,
8833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       Label* miss) {
8848defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Make sure there's no overlap between holder and object registers.
8853bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
8863bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
8873bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch         && !scratch2.is(scratch1));
88844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
8898defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Keep track of the current object in register reg.
8908defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Register reg = object_reg;
8913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSObject> current = object;
8928defd9ff6930b4e24729971a61cf7469daf119beSteve Block  int depth = 0;
8938defd9ff6930b4e24729971a61cf7469daf119beSteve Block
8948defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (save_at_depth == depth) {
8958defd9ff6930b4e24729971a61cf7469daf119beSteve Block    __ mov(Operand(esp, kPointerSize), reg);
8968defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8988defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Traverse the prototype chain and check the maps in the prototype chain for
8998defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // fast and global objects or do negative lookup for normal objects.
9003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while (!current.is_identical_to(holder)) {
9013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ++depth;
9028defd9ff6930b4e24729971a61cf7469daf119beSteve Block
9038defd9ff6930b4e24729971a61cf7469daf119beSteve Block    // Only global objects and objects that do not require access
9048defd9ff6930b4e24729971a61cf7469daf119beSteve Block    // checks are allowed in stubs.
9058defd9ff6930b4e24729971a61cf7469daf119beSteve Block    ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
9068defd9ff6930b4e24729971a61cf7469daf119beSteve Block
9073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> prototype(JSObject::cast(current->GetPrototype()));
9088defd9ff6930b4e24729971a61cf7469daf119beSteve Block    if (!current->HasFastProperties() &&
9098defd9ff6930b4e24729971a61cf7469daf119beSteve Block        !current->IsJSGlobalObject() &&
9108defd9ff6930b4e24729971a61cf7469daf119beSteve Block        !current->IsJSGlobalProxy()) {
9118defd9ff6930b4e24729971a61cf7469daf119beSteve Block      if (!name->IsSymbol()) {
9123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        name = factory()->LookupSymbol(name);
9138defd9ff6930b4e24729971a61cf7469daf119beSteve Block      }
9143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(current->property_dictionary()->FindEntry(*name) ==
9158defd9ff6930b4e24729971a61cf7469daf119beSteve Block             StringDictionary::kNotFound);
9168defd9ff6930b4e24729971a61cf7469daf119beSteve Block
9173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GenerateDictionaryNegativeLookup(masm(), miss, reg, name,
9183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       scratch1, scratch2);
919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
9203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
9213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      reg = holder_reg;  // From now on the object will be in holder_reg.
9223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
9233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
9243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      bool in_new_space = heap()->InNewSpace(*prototype);
9253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Map> current_map(current->map());
9263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (in_new_space) {
9273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Save the map in scratch1 for later.
9283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
9298defd9ff6930b4e24729971a61cf7469daf119beSteve Block      }
9303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK,
9313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  ALLOW_ELEMENT_TRANSITION_MAPS);
9323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check access rights to the global object.  This has to happen after
9343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // the map check so that we know that the object is actually a global
9353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // object.
9368defd9ff6930b4e24729971a61cf7469daf119beSteve Block      if (current->IsJSGlobalProxy()) {
9373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CheckAccessGlobalProxy(reg, scratch2, miss);
9383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
9393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      reg = holder_reg;  // From now on the object will be in holder_reg.
9403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (in_new_space) {
9423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // The prototype is in new space; we cannot store a reference to it
9433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // in the code.  Load it from the map.
9443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
9453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
9463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // The prototype is in old space; load it directly.
9473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ mov(reg, prototype);
948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
9508defd9ff6930b4e24729971a61cf7469daf119beSteve Block
9518defd9ff6930b4e24729971a61cf7469daf119beSteve Block    if (save_at_depth == depth) {
9528defd9ff6930b4e24729971a61cf7469daf119beSteve Block      __ mov(Operand(esp, kPointerSize), reg);
9538defd9ff6930b4e24729971a61cf7469daf119beSteve Block    }
9548defd9ff6930b4e24729971a61cf7469daf119beSteve Block
9558defd9ff6930b4e24729971a61cf7469daf119beSteve Block    // Go to the next object in the prototype chain.
9568defd9ff6930b4e24729971a61cf7469daf119beSteve Block    current = prototype;
957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
9583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(current.is_identical_to(holder));
9598defd9ff6930b4e24729971a61cf7469daf119beSteve Block
9608defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Log the check depth.
96144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
9628defd9ff6930b4e24729971a61cf7469daf119beSteve Block
9638defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Check the holder map.
9643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(reg, Handle<Map>(holder->map()),
9653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              miss, DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
9668defd9ff6930b4e24729971a61cf7469daf119beSteve Block
9678defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Perform security check for access to the global object.
9688defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
9698defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (holder->IsJSGlobalProxy()) {
9703bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    __ CheckAccessGlobalProxy(reg, scratch1, miss);
9713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
9723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If we've skipped any global objects, it's not enough to verify that
9743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // their maps haven't changed.  We also need to check that the property
9753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // cell for the property is still empty.
9763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss);
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
978402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Return the register containing the holder.
9798defd9ff6930b4e24729971a61cf7469daf119beSteve Block  return reg;
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadField(Handle<JSObject> object,
9843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Handle<JSObject> holder,
985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Register receiver,
986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Register scratch1,
987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Register scratch2,
9883bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                     Register scratch3,
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     int index,
9903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Handle<String> name,
991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Label* miss) {
992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
9933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver, miss);
994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the prototype chain.
9963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register reg = CheckPrototypes(
9973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the value from the properties.
1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateFastPropertyLoad(masm(), eax, reg, holder, index);
1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadCallback(Handle<JSObject> object,
10063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<JSObject> holder,
10073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Register receiver,
10083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Register name_reg,
10093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Register scratch1,
10103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Register scratch2,
10113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Register scratch3,
10123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<AccessorInfo> callback,
10133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<String> name,
10143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Label* miss) {
1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
10163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver, miss);
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the maps haven't changed.
10193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register reg = CheckPrototypes(object, receiver, holder, scratch1,
10203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 scratch2, scratch3, name, miss);
1021d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
10228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Insert additional parameters into the stack frame above return address.
10238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ASSERT(!scratch3.is(reg));
10248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ pop(scratch3);  // Get return address to place it below.
10258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(receiver);  // receiver
10273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(scratch2, esp);
10288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ASSERT(!scratch2.is(reg));
1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(reg);  // holder
10309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Push data from AccessorInfo.
10313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (isolate()->heap()->InNewSpace(callback->data())) {
10323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(scratch1, Immediate(callback));
10338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset));
10349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  } else {
10353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(Immediate(Handle<Object>(callback->data())));
10369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
10378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1038d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Save a pointer to where we pushed the arguments pointer.
10396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // This will be passed as the const AccessorInfo& to the C++ callback.
10408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ push(scratch2);
10418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
10428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ push(name_reg);  // name
10438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(ebx, esp);  // esp points to reference to name (handler).
10448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
10458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ push(scratch3);  // Restore return address.
1046d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
10473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // 3 elements array for v8::Arguments::values_, handler for name and pointer
10488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // to the values (it considered as smi in GC).
10498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const int kStackSpace = 5;
10508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const int kApiArgc = 2;
10518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
10523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ PrepareCallApiFunction(kApiArgc);
10538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(ApiParameterOperand(0), ebx);  // name.
10543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(ebx, Immediate(kPointerSize));
10558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(ApiParameterOperand(1), ebx);  // arguments pointer.
10568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1057e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emitting a stub call may try to allocate (if the code is not
1058e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // already generated).  Do not allow the assembler to perform a
1059e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // garbage collection but instead return the allocation failure
1060e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // object.
10613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address getter_address = v8::ToCData<Address>(callback->getter());
10623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallApiFunctionAndReturn(getter_address, kStackSpace);
1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadConstant(Handle<JSObject> object,
10673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<JSObject> holder,
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register receiver,
1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch1,
1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch2,
10713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                        Register scratch3,
10723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<JSFunction> value,
10733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<String> name,
1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Label* miss) {
1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
10763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver, miss);
1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the maps haven't changed.
10793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(
10803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the constant value.
10833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadHeapObject(eax, value);
1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object,
10893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           Handle<JSObject> interceptor_holder,
1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           LookupResult* lookup,
1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register receiver,
1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register name_reg,
1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register scratch1,
1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register scratch2,
10953bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                           Register scratch3,
10963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           Handle<String> name,
1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Label* miss) {
10987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(interceptor_holder->HasNamedInterceptor());
10997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
11007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Check that the receiver isn't a smi.
11023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver, miss);
11037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // So far the most popular follow ups for interceptor loads are FIELD
11057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // and CALLBACKS, so inline only them, other cases may be added
11067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // later.
11077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  bool compile_followup_inline = false;
11083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (lookup->IsFound() && lookup->IsCacheable()) {
11097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    if (lookup->type() == FIELD) {
11107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      compile_followup_inline = true;
11117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    } else if (lookup->type() == CALLBACKS &&
11123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               lookup->GetCallbackObject()->IsAccessorInfo()) {
11133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      compile_followup_inline =
11143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL;
11157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
11167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
11177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (compile_followup_inline) {
11197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Compile the interceptor call, followed by inline code to load the
11207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // property from further up the prototype chain if the call fails.
11217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Check that the maps haven't changed.
11227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
11233bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                          scratch1, scratch2, scratch3,
11243bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                          name, miss);
11257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1));
11267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11275710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch    // Preserve the receiver register explicitly whenever it is different from
11285710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch    // the holder and it is needed should the interceptor return without any
11295710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch    // result. The CALLBACKS case needs the receiver to be passed into C++ code,
11305710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch    // the FIELD case might cause a miss during the prototype check.
11315710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch    bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder();
11325710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch    bool must_preserve_receiver_reg = !receiver.is(holder_reg) &&
11335710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch        (lookup->type() == CALLBACKS || must_perfrom_prototype_check);
11345710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch
11357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Save necessary data before invoking an interceptor.
11367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Requires a frame to make GC aware of pushed pointers.
11373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    {
11383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FrameScope frame_scope(masm(), StackFrame::INTERNAL);
11397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11405710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch      if (must_preserve_receiver_reg) {
11413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ push(receiver);
11423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
11433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ push(holder_reg);
11443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ push(name_reg);
1145592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
11463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Invoke an interceptor.  Note: map checks from receiver to
11473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // interceptor's holder has been compiled before (see a caller
11483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // of this method.)
11493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CompileCallLoadPropertyWithInterceptor(masm(),
11503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             receiver,
11513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             holder_reg,
11523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             name_reg,
11533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             interceptor_holder);
11543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check if interceptor provided a value for property.  If it's
11563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // the case, return immediately.
11573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label interceptor_failed;
11583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ cmp(eax, factory()->no_interceptor_result_sentinel());
11593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(equal, &interceptor_failed);
11603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      frame_scope.GenerateLeaveFrame();
11613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ret(0);
11627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11635710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch      // Clobber registers when generating debug-code to provoke errors.
11643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&interceptor_failed);
11655710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch      if (FLAG_debug_code) {
11665710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch        __ mov(receiver, Immediate(BitCast<int32_t>(kZapValue)));
11675710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch        __ mov(holder_reg, Immediate(BitCast<int32_t>(kZapValue)));
11685710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch        __ mov(name_reg, Immediate(BitCast<int32_t>(kZapValue)));
11695710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch      }
11705710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch
11713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(name_reg);
11723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(holder_reg);
11735710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch      if (must_preserve_receiver_reg) {
11743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ pop(receiver);
11753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
11763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Leave the internal frame.
11783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
117985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
11807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Check that the maps from interceptor's holder to lookup's holder
11817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // haven't changed.  And load lookup's holder into holder_reg.
11825710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch    if (must_perfrom_prototype_check) {
11837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      holder_reg = CheckPrototypes(interceptor_holder,
11847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   holder_reg,
11853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Handle<JSObject>(lookup->holder()),
11867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   scratch1,
11877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   scratch2,
11883bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                   scratch3,
11897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   name,
11907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   miss);
11917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
11927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    if (lookup->type() == FIELD) {
11947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // We found FIELD property in prototype chain of interceptor's holder.
11957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Retrieve a field from field's holder.
11967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      GenerateFastPropertyLoad(masm(), eax, holder_reg,
11973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Handle<JSObject>(lookup->holder()),
11983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               lookup->GetFieldIndex());
11997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ ret(0);
12007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    } else {
12017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // We found CALLBACKS property in prototype chain of interceptor's
12027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // holder.
12037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ASSERT(lookup->type() == CALLBACKS);
12043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<AccessorInfo> callback(
12053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AccessorInfo::cast(lookup->GetCallbackObject()));
12067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ASSERT(callback->getter() != NULL);
12077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Tail call to runtime.
12097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Important invariant in CALLBACKS case: the code above must be
12107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // structured to never clobber |receiver| register.
12117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ pop(scratch2);  // return address
12127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(receiver);
12137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(holder_reg);
12143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(holder_reg, Immediate(callback));
12157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset));
12168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ push(holder_reg);
12177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(name_reg);
12187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(scratch2);  // restore return address
12197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ExternalReference ref =
122144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ExternalReference(IC_Utility(IC::kLoadCallbackProperty),
122244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            masm()->isolate());
12237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ TailCallExternalReference(ref, 5, 1);
12247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
12257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  } else {  // !compile_followup_inline
12267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Call the runtime system to load the interceptor.
12277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Check that the maps haven't changed.
12287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    Register holder_reg =
12297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        CheckPrototypes(object, receiver, interceptor_holder,
12303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                        scratch1, scratch2, scratch3, name, miss);
12317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ pop(scratch2);  // save old return address
12327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    PushInterceptorArguments(masm(), receiver, holder_reg,
12337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                             name_reg, interceptor_holder);
12347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ push(scratch2);  // restore old return address
12357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
123644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ExternalReference ref =
123744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad),
123844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          isolate());
12397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ TailCallExternalReference(ref, 5, 1);
12407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) {
12457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (kind_ == Code::KEYED_CALL_IC) {
12463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(ecx, Immediate(name));
1247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(not_equal, miss);
12487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
12497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
12507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
12533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSObject> holder,
12543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<String> name,
125559151504615d929945dc59db37bf1166937748c6Steve Block                                                   Label* miss) {
125659151504615d929945dc59db37bf1166937748c6Steve Block  ASSERT(holder->IsGlobalObject());
125759151504615d929945dc59db37bf1166937748c6Steve Block
125859151504615d929945dc59db37bf1166937748c6Steve Block  // Get the number of arguments.
125959151504615d929945dc59db37bf1166937748c6Steve Block  const int argc = arguments().immediate();
126059151504615d929945dc59db37bf1166937748c6Steve Block
126159151504615d929945dc59db37bf1166937748c6Steve Block  // Get the receiver from the stack.
126259151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
126359151504615d929945dc59db37bf1166937748c6Steve Block
126459151504615d929945dc59db37bf1166937748c6Steve Block
126559151504615d929945dc59db37bf1166937748c6Steve Block  // Check that the maps haven't changed.
12663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(edx, miss);
126759151504615d929945dc59db37bf1166937748c6Steve Block  CheckPrototypes(object, edx, holder, ebx, eax, edi, name, miss);
126859151504615d929945dc59db37bf1166937748c6Steve Block}
126959151504615d929945dc59db37bf1166937748c6Steve Block
127059151504615d929945dc59db37bf1166937748c6Steve Block
12713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateLoadFunctionFromCell(
12723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
12733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
12743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* miss) {
127559151504615d929945dc59db37bf1166937748c6Steve Block  // Get the value from the cell.
1276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (Serializer::enabled()) {
12773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(edi, Immediate(cell));
1278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset));
1279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
12803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(edi, Operand::Cell(cell));
1281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
128259151504615d929945dc59db37bf1166937748c6Steve Block
128359151504615d929945dc59db37bf1166937748c6Steve Block  // Check that the cell contains the same function.
12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (isolate()->heap()->InNewSpace(*function)) {
128559151504615d929945dc59db37bf1166937748c6Steve Block    // We can't embed a pointer to a function in new space so we have
128659151504615d929945dc59db37bf1166937748c6Steve Block    // to verify that the shared function info is unchanged. This has
128759151504615d929945dc59db37bf1166937748c6Steve Block    // the nice side effect that multiple closures based on the same
128859151504615d929945dc59db37bf1166937748c6Steve Block    // function can all use this call IC. Before we load through the
128959151504615d929945dc59db37bf1166937748c6Steve Block    // function, we have to verify that it still is a function.
12903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(edi, miss);
129159151504615d929945dc59db37bf1166937748c6Steve Block    __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
1292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(not_equal, miss);
129359151504615d929945dc59db37bf1166937748c6Steve Block
129459151504615d929945dc59db37bf1166937748c6Steve Block    // Check the shared function info. Make sure it hasn't changed.
129559151504615d929945dc59db37bf1166937748c6Steve Block    __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset),
129659151504615d929945dc59db37bf1166937748c6Steve Block           Immediate(Handle<SharedFunctionInfo>(function->shared())));
129759151504615d929945dc59db37bf1166937748c6Steve Block  } else {
12983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(edi, Immediate(function));
129959151504615d929945dc59db37bf1166937748c6Steve Block  }
13003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_equal, miss);
130159151504615d929945dc59db37bf1166937748c6Steve Block}
130259151504615d929945dc59db37bf1166937748c6Steve Block
130359151504615d929945dc59db37bf1166937748c6Steve Block
13043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateMissBranch() {
13053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> code =
130644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
1307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                               kind_,
13083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               extra_state_);
13093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(code, RelocInfo::CODE_TARGET);
13107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
13117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13133ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
13143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<JSObject> holder,
13153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                int index,
13163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<String> name) {
1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1318e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ecx                 : name
1319e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[0]              : return address
1320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
1321e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ...
1322e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc + 1) * 4] : receiver
1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateNameCheck(name, &miss);
13277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver from the stack.
1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
13333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(edx, &miss);
1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do the right check and compute the holder register.
13363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Register reg = CheckPrototypes(object, edx, holder, ebx, eax, edi,
13373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                 name, &miss);
1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateFastPropertyLoad(masm(), edi, reg, holder, index);
1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the function really is a function.
13423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(edi, &miss);
1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
1344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the receiver on the stack with the global proxy if
1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // necessary.
1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsGlobalObject()) {
1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the function.
13543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
1355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
1356257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
1357257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
1358257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), call_kind);
1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
13623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(FIELD, name);
1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13693ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPushCall(
13703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
13713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
13723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
13733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
13743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
13756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
13766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ecx                 : name
13776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- esp[0]              : return address
13786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
13796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ...
13806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- esp[(argc + 1) * 4] : receiver
13816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
13826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // If object is not an array, bail out to regular call.
13843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSArray() || !cell.is_null()) {
13853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Handle<Code>::null();
138644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
13876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss;
13896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateNameCheck(name, &miss);
13917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the receiver from the stack.
13936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int argc = arguments().immediate();
13946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
13956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the receiver isn't a smi.
13973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(edx, &miss);
13986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
14003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  name, &miss);
14016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (argc == 0) {
14036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Noop, return the length.
14046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
14056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ ret((argc + 1) * kPointerSize);
14066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
1407756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Label call_builtin;
1408756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
14093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (argc == 1) {  // Otherwise fall through to call builtin.
14103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label attempt_to_grow_elements, with_write_barrier;
14116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Get the elements array of the object.
14133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(edi, FieldOperand(edx, JSArray::kElementsOffset));
14145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
14153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check that the elements are in fast mode and writable.
14163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ cmp(FieldOperand(edi, HeapObject::kMapOffset),
14173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             Immediate(factory()->fixed_array_map()));
14183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(not_equal, &call_builtin);
14195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
14206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Get the array's length into eax and calculate new length.
14216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
14226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      STATIC_ASSERT(kSmiTagSize == 1);
14236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      STATIC_ASSERT(kSmiTag == 0);
14243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ add(eax, Immediate(Smi::FromInt(argc)));
14256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Get the elements' length into ecx.
14273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(ecx, FieldOperand(edi, FixedArray::kLengthOffset));
14286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Check if we could survive without allocation.
14303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ cmp(eax, ecx);
14316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ j(greater, &attempt_to_grow_elements);
14326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check if value is a smi.
14343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(ecx, Operand(esp, argc * kPointerSize));
14353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ JumpIfNotSmi(ecx, &with_write_barrier);
14363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Save new length.
14386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
14396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Store the value.
14413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(FieldOperand(edi,
14423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          eax,
14433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          times_half_pointer_size,
14443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          FixedArray::kHeaderSize - argc * kPointerSize),
14453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             ecx);
144685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
14476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ ret((argc + 1) * kPointerSize);
14486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ bind(&with_write_barrier);
14506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
14523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (FLAG_smi_only_arrays  && !FLAG_trace_elements_transitions) {
14543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Label fast_object, not_fast_object;
14553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CheckFastObjectElements(ebx, &not_fast_object, Label::kNear);
14563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ jmp(&fast_object);
14573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // In case of fast smi-only, convert to fast object, otherwise bail out.
14583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&not_fast_object);
14593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CheckFastSmiOnlyElements(ebx, &call_builtin);
14603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // edi: elements array
14613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // edx: receiver
14623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // ebx: map
14633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS,
14643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               FAST_ELEMENTS,
14653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               ebx,
14663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               edi,
14673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               &call_builtin);
14683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ElementsTransitionGenerator::GenerateSmiOnlyToObject(masm());
14693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Restore edi.
14703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ mov(edi, FieldOperand(edx, JSArray::kElementsOffset));
14713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&fast_object);
14723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
14733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CheckFastObjectElements(ebx, &call_builtin);
14743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
14753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Save new length.
14773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
14783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Store the value.
14803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lea(edx, FieldOperand(edi,
14813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               eax, times_half_pointer_size,
14823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               FixedArray::kHeaderSize - argc * kPointerSize));
14833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(Operand(edx, 0), ecx);
14843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ RecordWrite(edi, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
14863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     OMIT_SMI_CHECK);
14876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ ret((argc + 1) * kPointerSize);
14896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ bind(&attempt_to_grow_elements);
14915913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (!FLAG_inline_new) {
14925913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        __ jmp(&call_builtin);
14935913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
14945913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck
14953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(ebx, Operand(esp, argc * kPointerSize));
14963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Growing elements that are SMI-only requires special handling in case
14973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // the new element is non-Smi. For now, delegate to the builtin.
14983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label no_fast_elements_check;
14993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ JumpIfSmi(ebx, &no_fast_elements_check);
15003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
15013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CheckFastObjectElements(ecx, &call_builtin, Label::kFar);
15023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&no_fast_elements_check);
15033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // We could be lucky and the elements array could be at the top of
15053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // new-space.  In this case we can just grow it in place by moving the
15063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // allocation pointer up.
15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ExternalReference new_space_allocation_top =
150944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ExternalReference::new_space_allocation_top_address(isolate());
15106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ExternalReference new_space_allocation_limit =
151144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ExternalReference::new_space_allocation_limit_address(isolate());
15126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      const int kAllocationDelta = 4;
15146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Load top.
15156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ mov(ecx, Operand::StaticVariable(new_space_allocation_top));
15166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Check if it's the end of elements.
15183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lea(edx, FieldOperand(edi,
15196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               eax, times_half_pointer_size,
15206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               FixedArray::kHeaderSize - argc * kPointerSize));
15213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ cmp(edx, ecx);
15226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ j(not_equal, &call_builtin);
15233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ add(ecx, Immediate(kAllocationDelta * kPointerSize));
15246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ cmp(ecx, Operand::StaticVariable(new_space_allocation_limit));
15256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ j(above, &call_builtin);
15266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // We fit and could grow elements.
15286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ mov(Operand::StaticVariable(new_space_allocation_top), ecx);
15296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Push the argument...
15313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(Operand(edx, 0), ebx);
15326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // ... and fill the rest with holes.
15336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      for (int i = 1; i < kAllocationDelta; i++) {
15346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        __ mov(Operand(edx, i * kPointerSize),
153544f0eee88ff00398ff7f715fab053374d808c90dSteve Block               Immediate(factory()->the_hole_value()));
15366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
15376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // We know the elements array is in new space so we don't need the
15393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // remembered set, but we just pushed a value onto it so we may have to
15403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // tell the incremental marker to rescan the object that we just grew.  We
15413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // don't need to worry about the holes because they are in old space and
15423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // already marked black.
15433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ RecordWrite(edi, edx, ebx, kDontSaveFPRegs, OMIT_REMEMBERED_SET);
15443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Restore receiver to edx as finish sequence assumes it's here.
15466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
15476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Increment element's and array's sizes.
15493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ add(FieldOperand(edi, FixedArray::kLengthOffset),
15507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch             Immediate(Smi::FromInt(kAllocationDelta)));
15513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // NOTE: This only happen in new-space, where we don't
15533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // care about the black-byte-count on pages. Otherwise we should
15543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // update that too if the object is black.
15553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
15576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ ret((argc + 1) * kPointerSize);
15596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
15606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1561756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ bind(&call_builtin);
156244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ TailCallExternalReference(
156344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ExternalReference(Builtins::c_ArrayPush, isolate()),
156444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        argc + 1,
156544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        1);
15666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
15676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss);
15693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
15706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return the generated code.
157225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  return GetCode(function);
15736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
15746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPopCall(
15773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
15783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
15793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
15803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
15813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
15826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
15836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ecx                 : name
15846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- esp[0]              : return address
15856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
15866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ...
15876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- esp[(argc + 1) * 4] : receiver
15886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
15896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // If object is not an array, bail out to regular call.
15913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSArray() || !cell.is_null()) {
15923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Handle<Code>::null();
159344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
15946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss, return_undefined, call_builtin;
15966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateNameCheck(name, &miss);
15987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
15996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the receiver from the stack.
16006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int argc = arguments().immediate();
16016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
16026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the receiver isn't a smi.
16043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(edx, &miss);
16053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
16063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  name, &miss);
16076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the elements array of the object.
16096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset));
16106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1611756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Check that the elements are in fast mode and writable.
16126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
161344f0eee88ff00398ff7f715fab053374d808c90dSteve Block         Immediate(factory()->fixed_array_map()));
1614756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ j(not_equal, &call_builtin);
16156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the array's length into ecx and calculate new length.
16176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(ecx, FieldOperand(edx, JSArray::kLengthOffset));
16183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sub(ecx, Immediate(Smi::FromInt(1)));
16196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ j(negative, &return_undefined);
16206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the last element.
16226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  STATIC_ASSERT(kSmiTagSize == 1);
16236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  STATIC_ASSERT(kSmiTag == 0);
16246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(eax, FieldOperand(ebx,
16256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           ecx, times_half_pointer_size,
16266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           FixedArray::kHeaderSize));
16273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(eax, Immediate(factory()->the_hole_value()));
16286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ j(equal, &call_builtin);
16296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Set the array's length.
16316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(FieldOperand(edx, JSArray::kLengthOffset), ecx);
16326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Fill with the hole.
16346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(FieldOperand(ebx,
16356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      ecx, times_half_pointer_size,
16366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      FixedArray::kHeaderSize),
163744f0eee88ff00398ff7f715fab053374d808c90dSteve Block         Immediate(factory()->the_hole_value()));
16386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ret((argc + 1) * kPointerSize);
16396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&return_undefined);
164144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(eax, Immediate(factory()->undefined_value()));
16426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ret((argc + 1) * kPointerSize);
16436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&call_builtin);
164544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ TailCallExternalReference(
164644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(Builtins::c_ArrayPop, isolate()),
164744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      argc + 1,
164844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      1);
16496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss);
16513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
16527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
16537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Return the generated code.
16547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  return GetCode(function);
16557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
16567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
16577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
16583ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
16593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
16603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
16613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
16623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
16633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
16647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // ----------- S t a t e -------------
16657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- ecx                 : function name
16667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[0]              : return address
16677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
16687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- ...
16697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[(argc + 1) * 4] : receiver
16707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // -----------------------------------
16717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1672756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // If object is not a string, bail out to regular call.
16733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsString() || !cell.is_null()) {
16743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Handle<Code>::null();
167544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1676756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
16777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  const int argc = arguments().immediate();
16787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
16797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label miss;
1680b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label name_miss;
16817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
1682b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label* index_out_of_range_label = &index_out_of_range;
16839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
1684257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (kind_ == Code::CALL_IC &&
16853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      (CallICBase::StringStubState::decode(extra_state_) ==
1686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       DEFAULT_STRING_STUB)) {
1687b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    index_out_of_range_label = &miss;
1688b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1689b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1690b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  GenerateNameCheck(name, &name_miss);
16917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
16927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Check that the maps starting from the prototype haven't changed.
16937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateDirectLoadGlobalFunctionPrototype(masm(),
16947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                            Context::STRING_FUNCTION_INDEX,
16950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            eax,
16960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            &miss);
16973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!object.is_identical_to(holder));
16983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())),
16993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  eax, holder, ebx, edx, edi, name, &miss);
17007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
17017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register receiver = ebx;
17027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = edi;
17037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = eax;
17047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize));
17057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (argc > 0) {
17067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ mov(index, Operand(esp, (argc - 0) * kPointerSize));
17077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  } else {
170844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ Set(index, Immediate(factory()->undefined_value()));
17097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
17107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
17113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringCharCodeAtGenerator generator(receiver,
17123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      index,
17133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      result,
17143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      &miss,  // When not a string.
17153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      &miss,  // When not a number.
17163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      index_out_of_range_label,
17173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      STRING_INDEX_IS_NUMBER);
17183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateFast(masm());
17197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ ret((argc + 1) * kPointerSize);
17207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StubRuntimeCallHelper call_helper;
17223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateSlow(masm(), call_helper);
17237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1724b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (index_out_of_range.is_linked()) {
1725b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ bind(&index_out_of_range);
172644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ Set(eax, Immediate(factory()->nan_value()));
1727b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ ret((argc + 1) * kPointerSize);
1728b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
17297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
17307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&miss);
1731b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Restore function name in ecx.
17323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Set(ecx, Immediate(name));
1733b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&name_miss);
17343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
17357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
17367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Return the generated code.
17377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  return GetCode(function);
17387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
17397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
17407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
17413ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharAtCall(
17423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
17433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
17443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
17453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
17463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
17477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // ----------- S t a t e -------------
17487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- ecx                 : function name
17497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[0]              : return address
17507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
17517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- ...
17527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[(argc + 1) * 4] : receiver
17537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // -----------------------------------
17547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1755756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // If object is not a string, bail out to regular call.
17563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsString() || !cell.is_null()) {
17573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Handle<Code>::null();
175844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1759756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
17607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  const int argc = arguments().immediate();
17617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
17627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label miss;
1763b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label name_miss;
17647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
1765b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label* index_out_of_range_label = &index_out_of_range;
17667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (kind_ == Code::CALL_IC &&
17683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      (CallICBase::StringStubState::decode(extra_state_) ==
1769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       DEFAULT_STRING_STUB)) {
1770b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    index_out_of_range_label = &miss;
1771b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1772b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1773b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  GenerateNameCheck(name, &name_miss);
17747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
17757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Check that the maps starting from the prototype haven't changed.
17767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateDirectLoadGlobalFunctionPrototype(masm(),
17777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                            Context::STRING_FUNCTION_INDEX,
17780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            eax,
17790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            &miss);
17803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!object.is_identical_to(holder));
17813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())),
17823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  eax, holder, ebx, edx, edi, name, &miss);
17837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
17847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register receiver = eax;
17857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = edi;
17863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = edx;
17877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = eax;
17887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize));
17897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (argc > 0) {
17907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ mov(index, Operand(esp, (argc - 0) * kPointerSize));
17917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  } else {
179244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ Set(index, Immediate(factory()->undefined_value()));
17937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
17947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
17953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringCharAtGenerator generator(receiver,
17963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  index,
17973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  scratch,
17983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  result,
17993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  &miss,  // When not a string.
18003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  &miss,  // When not a number.
18013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  index_out_of_range_label,
18023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  STRING_INDEX_IS_NUMBER);
18033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateFast(masm());
18047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ ret((argc + 1) * kPointerSize);
18057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StubRuntimeCallHelper call_helper;
18073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateSlow(masm(), call_helper);
18087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1809b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (index_out_of_range.is_linked()) {
1810b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ bind(&index_out_of_range);
181144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ Set(eax, Immediate(factory()->empty_string()));
1812b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ ret((argc + 1) * kPointerSize);
1813b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
18147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
18157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&miss);
1816b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Restore function name in ecx.
18173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Set(ecx, Immediate(name));
1818b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&name_miss);
18193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
18206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return the generated code.
182225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  return GetCode(function);
18236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
18246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18263ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
18273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
18283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
18293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
18303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
18313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
183259151504615d929945dc59db37bf1166937748c6Steve Block  // ----------- S t a t e -------------
183359151504615d929945dc59db37bf1166937748c6Steve Block  //  -- ecx                 : function name
183459151504615d929945dc59db37bf1166937748c6Steve Block  //  -- esp[0]              : return address
183559151504615d929945dc59db37bf1166937748c6Steve Block  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
183659151504615d929945dc59db37bf1166937748c6Steve Block  //  -- ...
183759151504615d929945dc59db37bf1166937748c6Steve Block  //  -- esp[(argc + 1) * 4] : receiver
183859151504615d929945dc59db37bf1166937748c6Steve Block  // -----------------------------------
183959151504615d929945dc59db37bf1166937748c6Steve Block
184059151504615d929945dc59db37bf1166937748c6Steve Block  const int argc = arguments().immediate();
184159151504615d929945dc59db37bf1166937748c6Steve Block
184259151504615d929945dc59db37bf1166937748c6Steve Block  // If the object is not a JSObject or we got an unexpected number of
184359151504615d929945dc59db37bf1166937748c6Steve Block  // arguments, bail out to the regular call.
184444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!object->IsJSObject() || argc != 1) {
18453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Handle<Code>::null();
184644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
184759151504615d929945dc59db37bf1166937748c6Steve Block
184859151504615d929945dc59db37bf1166937748c6Steve Block  Label miss;
184959151504615d929945dc59db37bf1166937748c6Steve Block  GenerateNameCheck(name, &miss);
185059151504615d929945dc59db37bf1166937748c6Steve Block
18513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (cell.is_null()) {
185259151504615d929945dc59db37bf1166937748c6Steve Block    __ mov(edx, Operand(esp, 2 * kPointerSize));
185359151504615d929945dc59db37bf1166937748c6Steve Block    STATIC_ASSERT(kSmiTag == 0);
18543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(edx, &miss);
18553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
18563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    name, &miss);
185759151504615d929945dc59db37bf1166937748c6Steve Block  } else {
18583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(cell->value() == *function);
18593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
18603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                &miss);
186159151504615d929945dc59db37bf1166937748c6Steve Block    GenerateLoadFunctionFromCell(cell, function, &miss);
186259151504615d929945dc59db37bf1166937748c6Steve Block  }
186359151504615d929945dc59db37bf1166937748c6Steve Block
186459151504615d929945dc59db37bf1166937748c6Steve Block  // Load the char code argument.
186559151504615d929945dc59db37bf1166937748c6Steve Block  Register code = ebx;
186659151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(code, Operand(esp, 1 * kPointerSize));
186759151504615d929945dc59db37bf1166937748c6Steve Block
186859151504615d929945dc59db37bf1166937748c6Steve Block  // Check the code is a smi.
186959151504615d929945dc59db37bf1166937748c6Steve Block  Label slow;
187059151504615d929945dc59db37bf1166937748c6Steve Block  STATIC_ASSERT(kSmiTag == 0);
18713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(code, &slow);
187259151504615d929945dc59db37bf1166937748c6Steve Block
187359151504615d929945dc59db37bf1166937748c6Steve Block  // Convert the smi code to uint16.
187459151504615d929945dc59db37bf1166937748c6Steve Block  __ and_(code, Immediate(Smi::FromInt(0xffff)));
187559151504615d929945dc59db37bf1166937748c6Steve Block
18763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringCharFromCodeGenerator generator(code, eax);
18773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateFast(masm());
187859151504615d929945dc59db37bf1166937748c6Steve Block  __ ret(2 * kPointerSize);
187959151504615d929945dc59db37bf1166937748c6Steve Block
1880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StubRuntimeCallHelper call_helper;
18813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateSlow(masm(), call_helper);
188259151504615d929945dc59db37bf1166937748c6Steve Block
188359151504615d929945dc59db37bf1166937748c6Steve Block  // Tail call the full function. We do not have to patch the receiver
188459151504615d929945dc59db37bf1166937748c6Steve Block  // because the function makes no use of it.
188559151504615d929945dc59db37bf1166937748c6Steve Block  __ bind(&slow);
18863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
1887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
1888257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
1889257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
1890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), call_kind);
189159151504615d929945dc59db37bf1166937748c6Steve Block
189259151504615d929945dc59db37bf1166937748c6Steve Block  __ bind(&miss);
189359151504615d929945dc59db37bf1166937748c6Steve Block  // ecx: function name.
18943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
189559151504615d929945dc59db37bf1166937748c6Steve Block
189659151504615d929945dc59db37bf1166937748c6Steve Block  // Return the generated code.
18973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
189859151504615d929945dc59db37bf1166937748c6Steve Block}
189959151504615d929945dc59db37bf1166937748c6Steve Block
190059151504615d929945dc59db37bf1166937748c6Steve Block
19013ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathFloorCall(
19023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
19033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
19043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
19053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
19063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
19070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // ----------- S t a t e -------------
19080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  //  -- ecx                 : name
19090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  //  -- esp[0]              : return address
19100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
19110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  //  -- ...
19120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  //  -- esp[(argc + 1) * 4] : receiver
19130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // -----------------------------------
19140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (!CpuFeatures::IsSupported(SSE2)) {
19163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Handle<Code>::null();
191744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
191844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
19190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  CpuFeatures::Scope use_sse2(SSE2);
19200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  const int argc = arguments().immediate();
19220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // If the object is not a JSObject or we got an unexpected number of
19240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // arguments, bail out to the regular call.
192544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!object->IsJSObject() || argc != 1) {
19263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Handle<Code>::null();
192744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
19280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label miss;
19300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  GenerateNameCheck(name, &miss);
19310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (cell.is_null()) {
19330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ mov(edx, Operand(esp, 2 * kPointerSize));
19340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    STATIC_ASSERT(kSmiTag == 0);
19363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(edx, &miss);
19370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
19393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    name, &miss);
19400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
19413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(cell->value() == *function);
19423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
19433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                &miss);
19440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    GenerateLoadFunctionFromCell(cell, function, &miss);
19450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
19460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Load the (only) argument into eax.
19480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ mov(eax, Operand(esp, 1 * kPointerSize));
19490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Check if the argument is a smi.
19510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label smi;
19520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  STATIC_ASSERT(kSmiTag == 0);
19533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(eax, &smi);
19540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Check if the argument is a heap number and load its value into xmm0.
19560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label slow;
1957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ CheckMap(eax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK);
19580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ movdbl(xmm0, FieldOperand(eax, HeapNumber::kValueOffset));
19590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Check if the argument is strictly positive. Note this also
19610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // discards NaN.
19620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ xorpd(xmm1, xmm1);
19630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ ucomisd(xmm0, xmm1);
19640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ j(below_equal, &slow);
19650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Do a truncating conversion.
19670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ cvttsd2si(eax, Operand(xmm0));
19680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Check if the result fits into a smi. Note this also checks for
19700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // 0x80000000 which signals a failed conversion.
19710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label wont_fit_into_smi;
19720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ test(eax, Immediate(0xc0000000));
19730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ j(not_zero, &wont_fit_into_smi);
19740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Smi tag and return.
19760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ SmiTag(eax);
19770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&smi);
19780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ ret(2 * kPointerSize);
19790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Check if the argument is < 2^kMantissaBits.
19810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label already_round;
19820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&wont_fit_into_smi);
19830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadPowerOf2(xmm1, ebx, HeapNumber::kMantissaBits);
19840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ ucomisd(xmm0, xmm1);
19850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ j(above_equal, &already_round);
19860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Save a copy of the argument.
19880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ movaps(xmm2, xmm0);
19890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Compute (argument + 2^kMantissaBits) - 2^kMantissaBits.
19910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ addsd(xmm0, xmm1);
19920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ subsd(xmm0, xmm1);
19930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Compare the argument and the tentative result to get the right mask:
19950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  //   if xmm2 < xmm0:
19960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  //     xmm2 = 1...1
19970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  //   else:
19980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  //     xmm2 = 0...0
19990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ cmpltsd(xmm2, xmm0);
20000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
20010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Subtract 1 if the argument was less than the tentative result.
20020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadPowerOf2(xmm1, ebx, 0);
20030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ andpd(xmm1, xmm2);
20040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ subsd(xmm0, xmm1);
20050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
20060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Return a new heap number.
20070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ AllocateHeapNumber(eax, ebx, edx, &slow);
20080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
20090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ ret(2 * kPointerSize);
20100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
20110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Return the argument (when it's an already round heap number).
20120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&already_round);
20130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ mov(eax, Operand(esp, 1 * kPointerSize));
20140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ ret(2 * kPointerSize);
20150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
20160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Tail call the full function. We do not have to patch the receiver
20170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // because the function makes no use of it.
20180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&slow);
2019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
2020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), CALL_AS_METHOD);
20210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
20220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&miss);
20230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // ecx: function name.
20243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
20250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
20260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Return the generated code.
20273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
20280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
20290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
20300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
20313ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathAbsCall(
20323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
20333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
20343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
20353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
20363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2037f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // ----------- S t a t e -------------
2038f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- ecx                 : name
2039f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- esp[0]              : return address
2040f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
2041f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- ...
2042f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- esp[(argc + 1) * 4] : receiver
2043f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // -----------------------------------
2044f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2045f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const int argc = arguments().immediate();
2046f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2047f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // If the object is not a JSObject or we got an unexpected number of
2048f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // arguments, bail out to the regular call.
204944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!object->IsJSObject() || argc != 1) {
20503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Handle<Code>::null();
205144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
2052f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2053f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Label miss;
2054f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  GenerateNameCheck(name, &miss);
2055f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
20563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (cell.is_null()) {
2057f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    __ mov(edx, Operand(esp, 2 * kPointerSize));
2058f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2059f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    STATIC_ASSERT(kSmiTag == 0);
20603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(edx, &miss);
2061f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
20623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
20633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    name, &miss);
2064f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  } else {
20653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(cell->value() == *function);
20663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
20673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                &miss);
2068f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    GenerateLoadFunctionFromCell(cell, function, &miss);
2069f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
2070f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2071f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Load the (only) argument into eax.
2072f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ mov(eax, Operand(esp, 1 * kPointerSize));
2073f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2074f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Check if the argument is a smi.
2075f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Label not_smi;
2076f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
20773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(eax, &not_smi);
2078f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2079f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0
2080f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // otherwise.
2081f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ mov(ebx, eax);
2082f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ sar(ebx, kBitsPerInt - 1);
2083f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2084f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Do bitwise not or do nothing depending on ebx.
20853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ xor_(eax, ebx);
2086f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2087f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Add 1 or do nothing depending on ebx.
20883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sub(eax, ebx);
2089f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2090f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // If the result is still negative, go to the slow case.
2091f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // This only happens for the most negative smi.
2092f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Label slow;
2093f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ j(negative, &slow);
2094f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2095f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Smi case done.
2096f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ ret(2 * kPointerSize);
2097f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2098f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Check if the argument is a heap number and load its exponent and
2099f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // sign into ebx.
2100f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ bind(&not_smi);
2101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ CheckMap(eax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK);
2102f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ mov(ebx, FieldOperand(eax, HeapNumber::kExponentOffset));
2103f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2104f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Check the sign of the argument. If the argument is positive,
2105f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // just return it.
2106f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Label negative_sign;
2107f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ test(ebx, Immediate(HeapNumber::kSignMask));
2108f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ j(not_zero, &negative_sign);
2109f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ ret(2 * kPointerSize);
2110f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2111f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // If the argument is negative, clear the sign, and return a new
2112f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // number.
2113f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ bind(&negative_sign);
2114f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ and_(ebx, ~HeapNumber::kSignMask);
2115f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ mov(ecx, FieldOperand(eax, HeapNumber::kMantissaOffset));
2116f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ AllocateHeapNumber(eax, edi, edx, &slow);
2117f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ebx);
2118f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx);
2119f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ ret(2 * kPointerSize);
2120f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2121f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Tail call the full function. We do not have to patch the receiver
2122f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // because the function makes no use of it.
2123f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ bind(&slow);
2124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
2125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), CALL_AS_METHOD);
2126f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2127f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ bind(&miss);
2128f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // ecx: function name.
21293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2130f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2131f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Return the generated code.
21323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
2133f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
2134f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2135f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
21363ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileFastApiCall(
213744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    const CallOptimization& optimization,
21383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
21393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
21403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
21413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
21423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
214344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(optimization.is_simple_api_call());
214444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Bail out if object is a global object as we don't want to
214544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // repatch it to global receiver.
21463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (object->IsGlobalObject()) return Handle<Code>::null();
21473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!cell.is_null()) return Handle<Code>::null();
21483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSObject()) return Handle<Code>::null();
214944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int depth = optimization.GetPrototypeDepthOfExpectedType(
21503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<JSObject>::cast(object), holder);
21513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (depth == kInvalidProtoDepth) return Handle<Code>::null();
215244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
215344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label miss, miss_before_stack_reserved;
215444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
215544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenerateNameCheck(name, &miss_before_stack_reserved);
215644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
215744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Get the receiver from the stack.
215844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const int argc = arguments().immediate();
215944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
216044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
216144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the receiver isn't a smi.
21623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(edx, &miss_before_stack_reserved);
216344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
216444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
216544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_const(), 1);
216644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_const_fast_api(), 1);
216744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
216844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Allocate space for v8::Arguments implicit values. Must be initialized
216944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // before calling any runtime function.
21703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sub(esp, Immediate(kFastApiCallArguments * kPointerSize));
217144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
217244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the maps haven't changed and find a Holder as a side effect.
21733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
21743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  name, depth, &miss);
217544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
217644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Move the return address on top of the stack.
217744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(eax, Operand(esp, 3 * kPointerSize));
217844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(Operand(esp, 0 * kPointerSize), eax);
217944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
218044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains
218144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // duplicate of return address and will be overwritten.
21823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateFastApiCall(masm(), optimization, argc);
218344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
218444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&miss);
21853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(esp, Immediate(kFastApiCallArguments * kPointerSize));
218644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
218744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&miss_before_stack_reserved);
21883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
218944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
219044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Return the generated code.
219144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return GetCode(function);
219244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
219344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
219444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
21953ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object,
21963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSObject> holder,
21973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSFunction> function,
21983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<String> name,
21993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   CheckType check) {
2200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2201e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ecx                 : name
2202e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[0]              : return address
2203e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
2204e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ...
2205e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc + 1) * 4] : receiver
2206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
22076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
220844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (HasCustomCallGenerator(function)) {
22093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> code = CompileCustomCall(object, holder,
22103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          Handle<JSGlobalPropertyCell>::null(),
22113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          function, name);
22123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // A null handle means bail out to the regular compiler code below.
22133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!code.is_null()) return code;
22146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
22156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
221644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label miss;
221744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenerateNameCheck(name, &miss);
22187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver from the stack.
2220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
2221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
2222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
2224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (check != NUMBER_CHECK) {
22253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(edx, &miss);
2226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that it's okay not to patch the on stack receiver
2229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // unless we're doing a receiver map check.
2230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
2231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (check) {
2232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case RECEIVER_MAP_CHECK:
223344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ IncrementCounter(isolate()->counters()->call_const(), 1);
2234402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Check that the maps haven't changed.
22363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax,
22373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      edi, name, &miss);
2238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Patch the receiver on the stack with the global proxy if
2240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // necessary.
2241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (object->IsGlobalObject()) {
2242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
2243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
2244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
2245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
2246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case STRING_CHECK:
22483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
2249e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the object is a string or a symbol.
22507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax);
2251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ j(above_equal, &miss);
2252e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the maps starting from the prototype haven't changed.
22537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        GenerateDirectLoadGlobalFunctionPrototype(
22540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            masm(), Context::STRING_FUNCTION_INDEX, eax, &miss);
22553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CheckPrototypes(
22563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Handle<JSObject>(JSObject::cast(object->GetPrototype())),
22573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            eax, holder, ebx, edx, edi, name, &miss);
22583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
225985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        // Calling non-strict non-builtins with a value as the receiver
226085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        // requires boxing.
226185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        __ jmp(&miss);
22623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
22633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
22643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case NUMBER_CHECK:
22663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
2267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        Label fast;
2268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the object is a smi or a heap number.
22693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        __ JumpIfSmi(edx, &fast);
2270e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax);
2271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ j(not_equal, &miss);
2272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ bind(&fast);
2273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the maps starting from the prototype haven't changed.
22747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        GenerateDirectLoadGlobalFunctionPrototype(
22750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss);
22763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CheckPrototypes(
22773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Handle<JSObject>(JSObject::cast(object->GetPrototype())),
22783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            eax, holder, ebx, edx, edi, name, &miss);
22793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
228085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        // Calling non-strict non-builtins with a value as the receiver
228185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        // requires boxing.
228285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        __ jmp(&miss);
22833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
22843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
22853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case BOOLEAN_CHECK:
22873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
2288e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        Label fast;
2289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the object is a boolean.
229044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ cmp(edx, factory()->true_value());
2291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ j(equal, &fast);
229244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ cmp(edx, factory()->false_value());
2293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ j(not_equal, &miss);
2294e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ bind(&fast);
2295e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the maps starting from the prototype haven't changed.
22967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        GenerateDirectLoadGlobalFunctionPrototype(
22970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss);
22983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CheckPrototypes(
22993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Handle<JSObject>(JSObject::cast(object->GetPrototype())),
23003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            eax, holder, ebx, edx, edi, name, &miss);
23013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
23023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Calling non-strict non-builtins with a value as the receiver
23033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // requires boxing.
23043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ jmp(&miss);
2305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
2306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
2307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
2311257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
2312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
2313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), call_kind);
2314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
2316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
23173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
232025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  return GetCode(function);
2321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23243ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
23253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> holder,
23263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<String> name) {
2327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2328e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ecx                 : name
2329e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[0]              : return address
2330e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
2331e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ...
2332e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc + 1) * 4] : receiver
2333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateNameCheck(name, &miss);
23377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the number of arguments.
2339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
2340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LookupResult lookup(isolate());
2342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LookupPostInterceptor(holder, name, &lookup);
2343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver from the stack.
2345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
2346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallInterceptorCompiler compiler(this, arguments(), ecx, extra_state_);
23483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  compiler.Compile(masm(), object, holder, name, &lookup, edx, ebx, edi, eax,
23493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   &miss);
2350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Restore receiver.
2352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
2353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the function really is a function.
23553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(eax, &miss);
2356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
2357257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
2358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the receiver on the stack with the global proxy if
2360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // necessary.
2361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsGlobalObject()) {
2362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
2363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
2364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the function.
2367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(edi, eax);
23683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
2370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
2371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
2372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), call_kind);
2373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle load cache miss.
2375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
23763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23833ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallGlobal(
23843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
23853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<GlobalObject> holder,
23863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
23873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
23883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2390e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ecx                 : name
2391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[0]              : return address
2392e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
2393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ...
2394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc + 1) * 4] : receiver
2395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
239659151504615d929945dc59db37bf1166937748c6Steve Block
239744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (HasCustomCallGenerator(function)) {
23983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> code = CompileCustomCall(object, holder, cell, function, name);
23993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // A null handle means bail out to the regular compiler code below.
24003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!code.is_null()) return code;
240159151504615d929945dc59db37bf1166937748c6Steve Block  }
240259151504615d929945dc59db37bf1166937748c6Steve Block
2403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
24047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateNameCheck(name, &miss);
24057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the number of arguments.
2407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
240859151504615d929945dc59db37bf1166937748c6Steve Block  GenerateGlobalReceiverCheck(object, holder, name, &miss);
240959151504615d929945dc59db37bf1166937748c6Steve Block  GenerateLoadFunctionFromCell(cell, function, &miss);
2410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the receiver on the stack with the global proxy.
2412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsGlobalObject()) {
2413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
2414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
2415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the context (function already in edi).
2418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
2419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the cached code (tail call).
242144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
242244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_global_inline(), 1);
2423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount expected(function->shared()->formal_parameter_count());
24243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
2426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
24273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We call indirectly through the code field in the function to
24283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // allow recompilation to take effect without changing any of the
24293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // call sites.
24303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
24313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                expected, arguments(), JUMP_FUNCTION,
24323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                NullCallWrapper(), call_kind);
2433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
2435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
243644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_global_inline_miss(), 1);
24373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(NORMAL, name);
2441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24443ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
24455913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                  int index,
24463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                  Handle<Map> transition,
24473ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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  // Generate store field code.  Trashes the name register.
24573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateStoreField(masm(), object, index, transition, edx, ecx, ebx, &miss);
2458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
24613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(ecx, Immediate(name));  // restore name
246244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(ic, RelocInfo::CODE_TARGET);
2464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
24663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name);
2467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24703ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreCallback(
24713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
24723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<AccessorInfo> callback,
24733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- eax    : value
2476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
24774515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- edx    : receiver
2478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the object hasn't changed.
24833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(edx, Handle<Map>(object->map()),
24843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              &miss, DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
2485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform global security token check if needed.
2487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsJSGlobalProxy()) {
24884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ CheckAccessGlobalProxy(edx, ebx, &miss);
2489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub never generated for non-global objects that require access
2492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // checks.
2493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
2494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(ebx);  // remove the return address
24964515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ push(edx);  // receiver
24973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(Immediate(callback));  // callback info
2498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ecx);  // name
2499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(eax);  // value
2500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ebx);  // restore return address
2501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do tail-call to the runtime system.
2503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference store_callback_property =
250444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
25056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallExternalReference(store_callback_property, 4, 1);
2506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
250944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(ic, RelocInfo::CODE_TARGET);
2511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25173ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreInterceptor(
25183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
25193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- eax    : value
2522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
25234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- edx    : receiver
2524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the object hasn't changed.
25293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(edx, Handle<Map>(receiver->map()),
25303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              &miss, DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
2531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform global security token check if needed.
2533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (receiver->IsJSGlobalProxy()) {
25344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ CheckAccessGlobalProxy(edx, ebx, &miss);
2535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub never generated for non-global objects that require access
2538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // checks.
2539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
2540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(ebx);  // remove the return address
25424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ push(edx);  // receiver
2543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ecx);  // name
2544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(eax);  // value
2545e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ push(Immediate(Smi::FromInt(strict_mode_)));
2546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ebx);  // restore return address
2547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do tail-call to the runtime system.
2549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference store_ic_property =
255044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate());
2551e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ TailCallExternalReference(store_ic_property, 4, 1);
2552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
255544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(ic, RelocInfo::CODE_TARGET);
2557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25633ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreGlobal(
25643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<GlobalObject> object,
25653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
25663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- eax    : value
2569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
25704515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- edx    : receiver
2571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the global has not changed.
25764515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
2577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         Immediate(Handle<Map>(object->map())));
2578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
2579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Compute the cell operand to use.
25813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(ebx, Immediate(cell));
25823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Operand cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset);
2583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the value in the cell is not the hole. If it is, this
25851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // cell could have been deleted and reintroducing the global needs
25861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // to update the property details in the property dictionary of the
25871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // global object. We bail out to the runtime system to do that.
258844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmp(cell_operand, factory()->the_hole_value());
25891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ j(equal, &miss);
25901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
25911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Store the value in the cell.
25921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ mov(cell_operand, eax);
25933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // No write barrier here, because cells are always rescanned.
25941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the value (register eax).
259644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
259744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_store_global_inline(), 1);
2598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
2599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
260244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_store_global_inline_miss(), 1);
260344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(ic, RelocInfo::CODE_TARGET);
2605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(NORMAL, name);
2608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26113ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
26125913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                       int index,
26133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                       Handle<Map> transition,
26143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                       Handle<String> name) {
2615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- eax    : value
26176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ecx    : key
26186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- edx    : receiver
2619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
262344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
262444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_store_field(), 1);
2625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
26273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(ecx, Immediate(name));
2628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
2629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Generate store field code.  Trashes the name register.
26313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateStoreField(masm(), object, index, transition, edx, ecx, ebx, &miss);
2632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
263544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_store_field(), 1);
263644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(ic, RelocInfo::CODE_TARGET);
2638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
26403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name);
2641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26443ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreElement(
26453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Map> receiver_map) {
2646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // ----------- S t a t e -------------
2647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- eax    : value
2648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- ecx    : key
2649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- edx    : receiver
2650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- esp[0] : return address
2651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // -----------------------------------
2652589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ElementsKind elements_kind = receiver_map->elements_kind();
26533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
26543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> stub =
26553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      KeyedStoreElementStub(is_jsarray, elements_kind, grow_mode_).GetCode();
26563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK);
2658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(ic, RelocInfo::CODE_TARGET);
2661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
26633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string());
2664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
26673ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
26683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MapHandleList* receiver_maps,
26693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CodeHandleList* handler_stubs,
26703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MapHandleList* transitioned_maps) {
2671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- eax    : value
2673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ecx    : key
2674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- edx    : receiver
2675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- esp[0] : return address
2676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
26783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(edx, &miss, Label::kNear);
26793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
26803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ebx: receiver->map().
26813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < receiver_maps->length(); ++i) {
26823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(edi, receiver_maps->at(i));
26833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (transitioned_maps->at(i).is_null()) {
26843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(equal, handler_stubs->at(i));
26853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
26863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label next_map;
26873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(not_equal, &next_map, Label::kNear);
26883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(ebx, Immediate(transitioned_maps->at(i)));
26893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET);
26903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&next_map);
26913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&miss);
2694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss();
2695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
2696e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2697e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Return the generated code.
26983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC);
2699e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2700e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2701e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
27023ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name,
27033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> object,
27043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> last) {
27056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
27066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- eax    : receiver
27076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ecx    : name
27086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- esp[0] : return address
27096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
27106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss;
27116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the receiver isn't a smi.
27133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(eax, &miss);
27146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27158defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ASSERT(last->IsGlobalObject() || last->HasFastProperties());
27168defd9ff6930b4e24729971a61cf7469daf119beSteve Block
27176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the maps of the full prototype chain. Also check that
27186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // global property cells up to (but not including) the last object
27196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // in the prototype chain are empty.
27203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss);
27216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // If the last object in the prototype chain is a global object,
27236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // check that the global property cell is empty.
27246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (last->IsGlobalObject()) {
27253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateCheckPropertyCell(
27263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        masm(), Handle<GlobalObject>::cast(last), name, edx, &miss);
27276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
27286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return undefined if maps of the full prototype chain are still the
27306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // same and no global property with this name contains a value.
273144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(eax, isolate()->factory()->undefined_value());
27326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ret(0);
27336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss);
27356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
27366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return the generated code.
27383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NONEXISTENT, factory()->empty_string());
27396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
27406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27423ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object,
27433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<JSObject> holder,
27445913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                int index,
27453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<String> name) {
2746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2747402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : receiver
2748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
2749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27533bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  GenerateLoadField(object, holder, eax, ebx, edx, edi, index, name, &miss);
2754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(FIELD, name);
2759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27623ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadCallback(
27633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
27643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
27653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
27663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<AccessorInfo> callback) {
2767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2768402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : receiver
2769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
2770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadCallback(object, holder, eax, ecx, ebx, edx, edi, callback,
27753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       name, &miss);
2776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27843ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object,
27853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSObject> holder,
27863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSFunction> value,
27873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<String> name) {
2788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2789402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : receiver
2790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
2791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27953bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  GenerateLoadConstant(object, holder, eax, ebx, edx, edi, value, name, &miss);
2796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CONSTANT_FUNCTION, name);
2801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28043ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> receiver,
28053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> holder,
28063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<String> name) {
2807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2808402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : receiver
2809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
2810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LookupResult lookup(isolate());
2815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LookupPostInterceptor(holder, name, &lookup);
2816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // TODO(368): Compile in the whole chain: all the interceptors in
2818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // prototypes and ultimate answer.
28193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadInterceptor(receiver, holder, &lookup, eax, ecx, edx, ebx, edi,
28203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          name, &miss);
2821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28303ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadGlobal(
28313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
28323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<GlobalObject> holder,
28333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
28343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
28353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool is_dont_delete) {
2836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2837402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : receiver
2838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
2839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the maps haven't changed.
28443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(eax, &miss);
28453bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CheckPrototypes(object, eax, holder, ebx, edx, edi, name, &miss);
2846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the value from the cell.
2848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (Serializer::enabled()) {
28493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(ebx, Immediate(cell));
2850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset));
2851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
28523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(ebx, Operand::Cell(cell));
2853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for deleted property if property can actually be deleted.
2856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!is_dont_delete) {
285744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmp(ebx, factory()->the_hole_value());
2858257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(equal, &miss);
2859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (FLAG_debug_code) {
286044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmp(ebx, factory()->the_hole_value());
2861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Check(not_equal, "DontDelete cells can't contain the hole");
2862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
286444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
286544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_load_global_stub(), 1);
2866402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(eax, ebx);
2867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
2868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
287044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_load_global_stub_miss(), 1);
2871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(NORMAL, name);
2875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28783ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name,
28793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     Handle<JSObject> receiver,
28803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     Handle<JSObject> holder,
28815913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                     int index) {
2882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2883402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
2884402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
2885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
288944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
289044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_field(), 1);
2891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
28933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(eax, Immediate(name));
2894257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
2895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28963bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss);
2897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
289944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_field(), 1);
2900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(FIELD, name);
2904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29073ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadCallback(
29083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
29093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
29103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
29113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<AccessorInfo> callback) {
2912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2913402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
2914402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
2915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
291944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
292044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_callback(), 1);
2921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
29233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(eax, Immediate(name));
2924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
2925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadCallback(receiver, holder, edx, eax, ebx, ecx, edi, callback,
29273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       name, &miss);
2928e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
293044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_callback(), 1);
2931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29383ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadConstant(
29393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
29403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
29413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
29423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> value) {
2943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2944402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
2945402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
2946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
295044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
295144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_constant_function(), 1);
2952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
29543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(eax, Immediate(name));
2955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
2956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadConstant(
29583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      receiver, holder, edx, ebx, ecx, edi, value, name, &miss);
2959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
296044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_constant_function(), 1);
2961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CONSTANT_FUNCTION, name);
2965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29683ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor(
29693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
29703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
29713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2973402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
2974402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
2975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
297944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
298044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_interceptor(), 1);
2981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
29833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(eax, Immediate(name));
2984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
2985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LookupResult lookup(isolate());
2987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LookupPostInterceptor(holder, name, &lookup);
29883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadInterceptor(receiver, holder, &lookup, edx, eax, ecx, ebx, edi,
29893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          name, &miss);
2990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
299144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_interceptor(), 1);
2992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29993ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength(
30003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
3001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
3002402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
3003402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
3004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
3005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
3006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
3007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
300844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
300944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_array_length(), 1);
3010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
30123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(eax, Immediate(name));
3013257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
3014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3015402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateLoadArrayLength(masm(), edx, ecx, &miss);
3016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
301744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_array_length(), 1);
3018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
3021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
3022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30253ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadStringLength(
30263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
3027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
3028402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
3029402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
3030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
3031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
3032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
3033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
303444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
303544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_string_length(), 1);
3036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
30383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(eax, Immediate(name));
3039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
3040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true);
3042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
304344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_string_length(), 1);
3044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
3047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
3048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30513ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype(
30523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
3053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
3054402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
3055402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
3056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
3057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
3058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
3059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
306044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
306144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_function_prototype(), 1);
3062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
30643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(eax, Immediate(name));
3065257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
3066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3067402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss);
3068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
306944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_function_prototype(), 1);
3070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
3073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
3074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30773ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadElement(
30783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Map> receiver_map) {
3079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // ----------- S t a t e -------------
3080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- eax    : key
3081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- edx    : receiver
3082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- esp[0] : return address
3083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // -----------------------------------
30843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3085589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ElementsKind elements_kind = receiver_map->elements_kind();
30863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode();
30873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK);
3089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3090257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
30933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string());
3094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
30973ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic(
30983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MapHandleList* receiver_maps,
30993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CodeHandleList* handler_ics) {
3100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- eax    : key
3102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- edx    : receiver
3103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- esp[0] : return address
3104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
3106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfSmi(edx, &miss);
3107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register map_reg = ebx;
3109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(map_reg, FieldOperand(edx, HeapObject::kMapOffset));
3110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int receiver_count = receiver_maps->length();
3111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int current = 0; current < receiver_count; ++current) {
31123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(map_reg, receiver_maps->at(current));
31133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(equal, handler_ics->at(current));
3114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&miss);
3117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Return the generated code.
31203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC);
3121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Specialized stub for constructing objects from functions which only have only
3125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// simple assignments of the form this.x = ...; in their body.
31263ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> ConstructStubCompiler::CompileConstructStub(
31273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function) {
3128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
3129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- eax : argc
3130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- edi : constructor
3131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
3132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[4] : last argument
3133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
3134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label generic_stub_call;
3135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
3136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check to see whether there are any break points in the function code. If
3137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // there are jump to the generic constructor stub which calls the actual
3138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // code for the function thereby hitting the break points.
3139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
3140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kDebugInfoOffset));
314144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmp(ebx, factory()->undefined_value());
3142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &generic_stub_call);
3143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
3144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the initial map and verify that it is in fact a map.
3146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
3147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Will both indicate a NULL and a Smi.
31483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(ebx, &generic_stub_call);
3149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpObjectType(ebx, MAP_TYPE, ecx);
3150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &generic_stub_call);
3151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
3153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Cannot construct functions this way.
3154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // edi: constructor
3155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ebx: initial map
3156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpInstanceType(ebx, JS_FUNCTION_TYPE);
3157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Assert(not_equal, "Function constructed by construct stub.");
3158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
3159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Now allocate the JSObject on the heap by moving the new space allocation
3161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // top forward.
3162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // edi: constructor
3163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ebx: initial map
3164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset));
3165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ shl(ecx, kPointerSizeLog2);
31663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ AllocateInNewSpace(ecx, edx, ecx, no_reg,
31673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        &generic_stub_call, NO_ALLOCATION_FLAGS);
3168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocated the JSObject, now initialize the fields and add the heap tag.
3170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ebx: initial map
3171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // edx: JSObject (untagged)
3172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(Operand(edx, JSObject::kMapOffset), ebx);
317344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(ebx, factory()->empty_fixed_array());
3174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(Operand(edx, JSObject::kPropertiesOffset), ebx);
3175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(Operand(edx, JSObject::kElementsOffset), ebx);
3176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Push the allocated object to the stack. This is the object that will be
3178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // returned (after it is tagged).
3179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(edx);
3180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // eax: argc
3182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // edx: JSObject (untagged)
3183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the address of the first in-object property into edx.
3184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ lea(edx, Operand(edx, JSObject::kHeaderSize));
3185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate the location of the first argument. The stack contains the
3186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // allocated object and the return address on top of the argc arguments.
3187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ lea(ecx, Operand(esp, eax, times_4, 1 * kPointerSize));
3188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use edi for holding undefined which is used in several places below.
319044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(edi, factory()->undefined_value());
3191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // eax: argc
3193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ecx: first argument
3194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // edx: first in-object property of the JSObject
3195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // edi: undefined
3196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill the initialized properties with a constant value or a passed argument
3197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // depending on the this.x = ...; assignment in the function.
31983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<SharedFunctionInfo> shared(function->shared());
3199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < shared->this_property_assignments_count(); i++) {
3200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (shared->IsThisPropertyAssignmentArgument(i)) {
3201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Check if the argument assigned to the property is actually passed.
3202e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // If argument is not passed the property is set to undefined,
3203e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // otherwise find it on the stack.
3204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int arg_number = shared->GetThisPropertyAssignmentArgument(i);
3205e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ mov(ebx, edi);
3206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ cmp(eax, arg_number);
32078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (CpuFeatures::IsSupported(CMOV)) {
3208e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        CpuFeatures::Scope use_cmov(CMOV);
3209e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ cmov(above, ebx, Operand(ecx, arg_number * -kPointerSize));
3210e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
3211e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        Label not_passed;
3212e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ j(below_equal, &not_passed);
3213e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ mov(ebx, Operand(ecx, arg_number * -kPointerSize));
3214e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ bind(&not_passed);
3215e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3216e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Store value in the property.
3217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ mov(Operand(edx, i * kPointerSize), ebx);
3218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
3219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Set the property to the constant value.
3220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i));
3221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ mov(Operand(edx, i * kPointerSize), Immediate(constant));
3222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
3223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill the unused in-object property fields with undefined.
32268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ASSERT(function->has_initial_map());
3227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = shared->this_property_assignments_count();
32288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang       i < function->initial_map()->inobject_properties();
3229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       i++) {
3230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(Operand(edx, i * kPointerSize), edi);
3231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move argc to ebx and retrieve and tag the JSObject to return.
3234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(ebx, eax);
3235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(eax);
32363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ or_(eax, Immediate(kHeapObjectTag));
3237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Remove caller arguments and receiver from the stack and return.
3239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(ecx);
3240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ lea(esp, Operand(esp, ebx, times_pointer_size, 1 * kPointerSize));
3241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ecx);
324244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
324344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->constructed_objects(), 1);
324444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->constructed_objects_stub(), 1);
3245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
3246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the generic stub in case the specialized code cannot handle the
3248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // construction.
3249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&generic_stub_call);
32503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> code = isolate()->builtins()->JSConstructStubGeneric();
32513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(code, RelocInfo::CODE_TARGET);
3252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
3254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode();
3255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
32583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#undef __
32593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#define __ ACCESS_MASM(masm)
32603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
32613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
32623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
32633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MacroAssembler* masm) {
32641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ----------- S t a t e -------------
32651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- eax    : key
32661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- edx    : receiver
32671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- esp[0] : return address
32681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
32693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label slow, miss_force_generic;
3270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
32713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
32723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // have been verified by the caller to not be a smi.
32733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(eax, &miss_force_generic);
32743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(ebx, eax);
32753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SmiUntag(ebx);
32763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
32771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
32783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Push receiver on the stack to free up a register for the dictionary
32793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // probing.
32803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ push(edx);
32813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ LoadFromNumberDictionary(&slow,
32823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              ecx,
32833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              eax,
32843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              ebx,
32853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              edx,
32863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              edi,
32873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              eax);
32883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Pop receiver before returning.
32893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ pop(edx);
32903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ret(0);
3291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
32923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&slow);
32933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ pop(edx);
3294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- eax    : value
3297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ecx    : key
3298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- edx    : receiver
3299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- esp[0] : return address
3300257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
33023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> slow_ic =
33033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_Slow();
33043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(slow_ic, RelocInfo::CODE_TARGET);
3305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
33063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&miss_force_generic);
33073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ----------- S t a t e -------------
33083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- eax    : value
33093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- ecx    : key
33103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- edx    : receiver
33113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- esp[0] : return address
33123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
3313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
33143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> miss_force_generic_ic =
33153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
33163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(miss_force_generic_ic, RelocInfo::CODE_TARGET);
33173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
3318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadExternalArray(
3321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    MacroAssembler* masm,
3322589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    ElementsKind elements_kind) {
3323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- eax    : key
3325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- edx    : receiver
3326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- esp[0] : return address
3327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss_force_generic, failed_allocation, slow;
3329257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
3331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
33321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the key is a smi.
33343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(eax, &miss_force_generic);
33351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the index is in range.
3337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
333869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ cmp(eax, FieldOperand(ebx, ExternalArray::kLengthOffset));
33391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Unsigned comparison catches both negative and too-large values.
3340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(above_equal, &miss_force_generic);
33411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset));
33421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ebx: base pointer of external storage
33433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  switch (elements_kind) {
3344589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_BYTE_ELEMENTS:
334569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ SmiUntag(eax);  // Untag the index.
334669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ movsx_b(eax, Operand(ebx, eax, times_1, 0));
33471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3348589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3349589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_PIXEL_ELEMENTS:
335069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ SmiUntag(eax);  // Untag the index.
335169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ movzx_b(eax, Operand(ebx, eax, times_1, 0));
33521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3353589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_SHORT_ELEMENTS:
335469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ movsx_w(eax, Operand(ebx, eax, times_1, 0));
33551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3356589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
335769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ movzx_w(eax, Operand(ebx, eax, times_1, 0));
33581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3359589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
3360589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_INT_ELEMENTS:
336169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ mov(ecx, Operand(ebx, eax, times_2, 0));
33621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3363589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_FLOAT_ELEMENTS:
336469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ fld_s(Operand(ebx, eax, times_2, 0));
33651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3366589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_DOUBLE_ELEMENTS:
336769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ fld_d(Operand(ebx, eax, times_4, 0));
3368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
33691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    default:
33701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      UNREACHABLE();
33711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
33721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
33731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // For integer array types:
33751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ecx: value
33761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // For floating-point array type:
33771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // FP(0): value
33781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3379589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (elements_kind == EXTERNAL_INT_ELEMENTS ||
3380589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) {
33811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // For the Int and UnsignedInt array types, we need to see whether
33821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // the value can be represented in a Smi. If not, we need to convert
33831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // it to a HeapNumber.
33841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Label box_int;
3385589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (elements_kind == EXTERNAL_INT_ELEMENTS) {
33861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ cmp(ecx, 0xC0000000);
33871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ j(sign, &box_int);
33881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    } else {
3389589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind);
33901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // The test is different for unsigned int values. Since we need
33911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // the value to be in the range of a positive smi, we can't
33921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // handle either of the top two bits being set in the value.
33931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ test(ecx, Immediate(0xC0000000));
33941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ j(not_zero, &box_int);
33951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
33961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ mov(eax, ecx);
33981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ SmiTag(eax);
33991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ ret(0);
34001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ bind(&box_int);
34021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Allocate a HeapNumber for the int and perform int-to-double
34041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // conversion.
3405589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (elements_kind == EXTERNAL_INT_ELEMENTS) {
34061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ push(ecx);
34071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ fild_s(Operand(esp, 0));
34081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ pop(ecx);
34091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    } else {
3410589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind);
34111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Need to zero-extend the value.
34121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // There's no fild variant for unsigned values, so zero-extend
34131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // to a 64-bit int manually.
34141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ push(Immediate(0));
34151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ push(ecx);
34161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ fild_d(Operand(esp, 0));
34171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ pop(ecx);
34181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ pop(ecx);
34191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
34201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // FP(0): value
34211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation);
34221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Set the value.
34231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ mov(eax, ecx);
34241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
34251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ ret(0);
3426589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
3427589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch             elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
34281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // For the floating-point array type, we need to always allocate a
34291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // HeapNumber.
34301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation);
34311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Set the value.
34321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ mov(eax, ecx);
34331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
34341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ ret(0);
34351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
34361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ SmiTag(eax);
34371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ ret(0);
34381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
34391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // If we fail allocation of the HeapNumber, we still have a value on
34411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // top of the FPU stack. Remove it.
34421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&failed_allocation);
34433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ fstp(0);
34441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Fall through to slow case.
34451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Slow case: Jump to runtime.
34471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&slow);
3448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Counters* counters = masm->isolate()->counters();
344944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_external_array_slow(), 1);
3450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
34511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ----------- S t a t e -------------
34521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- eax    : key
34531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- edx    : receiver
34541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- esp[0] : return address
34551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
34561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Slow();
3458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(ic, RelocInfo::CODE_TARGET);
34591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- eax    : key
3462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- edx    : receiver
3463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- esp[0] : return address
3464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
34651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Miss case: Jump to runtime.
3467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
3468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> miss_ic =
3469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
34711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
34721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreExternalArray(
3475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    MacroAssembler* masm,
3476589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    ElementsKind elements_kind) {
34771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ----------- S t a t e -------------
3478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- eax    : key
34791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- edx    : receiver
34801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- esp[0] : return address
34811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
3482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss_force_generic, slow, check_heap_number;
348344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
3485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
348644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
34871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the key is a smi.
34883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(ecx, &miss_force_generic);
34891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the index is in range.
349144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
349269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ cmp(ecx, FieldOperand(edi, ExternalArray::kLengthOffset));
34931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Unsigned comparison catches both negative and too-large values.
34941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ j(above_equal, &slow);
34951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Handle both smis and HeapNumbers in the fast path. Go to the
34971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // runtime for all other kinds of values.
34981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // eax: value
34991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // edx: receiver
35001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ecx: key
35011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // edi: elements array
3502589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) {
35033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfNotSmi(eax, &slow);
35043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
35053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfNotSmi(eax, &check_heap_number);
35063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
350744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
35081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // smi case
350969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ mov(ebx, eax);  // Preserve the value in eax as the return value.
351069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ SmiUntag(ebx);
35111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
351269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // edi: base pointer of external storage
35133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  switch (elements_kind) {
3514589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_PIXEL_ELEMENTS:
351569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ ClampUint8(ebx);
351669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ SmiUntag(ecx);
351769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ mov_b(Operand(edi, ecx, times_1, 0), ebx);
351844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      break;
3519589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_BYTE_ELEMENTS:
3520589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
352169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ SmiUntag(ecx);
352269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ mov_b(Operand(edi, ecx, times_1, 0), ebx);
35231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3524589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_SHORT_ELEMENTS:
3525589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
352669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ mov_w(Operand(edi, ecx, times_1, 0), ebx);
35271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3528589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_INT_ELEMENTS:
3529589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
353069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ mov(Operand(edi, ecx, times_2, 0), ebx);
35311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3532589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_FLOAT_ELEMENTS:
3533589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_DOUBLE_ELEMENTS:
35341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Need to perform int-to-float conversion.
353569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ push(ebx);
35361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ fild_s(Operand(esp, 0));
353769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ pop(ebx);
3538589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
353969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ fstp_s(Operand(edi, ecx, times_2, 0));
3540589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      } else {  // elements_kind == EXTERNAL_DOUBLE_ELEMENTS.
354169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ fstp_d(Operand(edi, ecx, times_4, 0));
3542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
35431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
35441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    default:
35451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      UNREACHABLE();
35461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
35471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
35481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ ret(0);  // Return the original value.
35491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
355044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // TODO(danno): handle heap number -> pixel array conversion
3551589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) {
355244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ bind(&check_heap_number);
355344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // eax: value
355444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // edx: receiver
355544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // ecx: key
355644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // edi: elements array
355744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
3558257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch           Immediate(masm->isolate()->factory()->heap_number_map()));
355944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ j(not_equal, &slow);
356044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
356144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // The WebGL specification leaves the behavior of storing NaN and
356244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // +/-Infinity into integer arrays basically undefined. For more
356344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // reproducible behavior, convert these to zero.
356444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
356544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // edi: base pointer of external storage
3566589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
356744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
356869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ fstp_s(Operand(edi, ecx, times_2, 0));
356944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ ret(0);
3570589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
3571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
357269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ fstp_d(Operand(edi, ecx, times_4, 0));
3573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ ret(0);
357444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else {
357544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Perform float-to-int conversion with truncation (round-to-zero)
357644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // behavior.
357744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
357844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // For the moment we make the slow call to the runtime on
357944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // processors that don't support SSE2. The code in IntegerConvert
358044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // (code-stubs-ia32.cc) is roughly what is needed here though the
358144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // conversion failure case does not need to be handled.
35828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (CpuFeatures::IsSupported(SSE2)) {
3583589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        if (elements_kind != EXTERNAL_INT_ELEMENTS &&
3584589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            elements_kind != EXTERNAL_UNSIGNED_INT_ELEMENTS) {
35858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          ASSERT(CpuFeatures::IsSupported(SSE2));
35861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          CpuFeatures::Scope scope(SSE2);
358769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          __ cvttsd2si(ebx, FieldOperand(eax, HeapNumber::kValueOffset));
358844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          // ecx: untagged integer value
35893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          switch (elements_kind) {
3590589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            case EXTERNAL_PIXEL_ELEMENTS:
359169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              __ ClampUint8(ebx);
359269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              // Fall through.
3593589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            case EXTERNAL_BYTE_ELEMENTS:
3594589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
359569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              __ SmiUntag(ecx);
359669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              __ mov_b(Operand(edi, ecx, times_1, 0), ebx);
359744f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
3598589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            case EXTERNAL_SHORT_ELEMENTS:
3599589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
360069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              __ mov_w(Operand(edi, ecx, times_1, 0), ebx);
360144f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
360244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            default:
360344f0eee88ff00398ff7f715fab053374d808c90dSteve Block              UNREACHABLE();
360444f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
360544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          }
360644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
36078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          if (CpuFeatures::IsSupported(SSE3)) {
360844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            CpuFeatures::Scope scope(SSE3);
360944f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // fisttp stores values as signed integers. To represent the
361044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // entire range of int and unsigned int arrays, store as a
361144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // 64-bit int and discard the high 32 bits.
361244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // If the value is NaN or +/-infinity, the result is 0x80000000,
361344f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // which is automatically zero when taken mod 2^n, n < 32.
361444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
36153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ sub(esp, Immediate(2 * kPointerSize));
361644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            __ fisttp_d(Operand(esp, 0));
361769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            __ pop(ebx);
36183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ add(esp, Immediate(kPointerSize));
361944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else {
36208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            ASSERT(CpuFeatures::IsSupported(SSE2));
362144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            CpuFeatures::Scope scope(SSE2);
362244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // We can easily implement the correct rounding behavior for the
362344f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // range [0, 2^31-1]. For the time being, to keep this code simple,
362444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // make the slow runtime call for values outside this range.
362544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // Note: we could do better for signed int arrays.
362644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            __ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset));
362744f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // We will need the key if we have to make the slow runtime call.
362869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            __ push(ebx);
362969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            __ LoadPowerOf2(xmm1, ebx, 31);
363069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            __ pop(ebx);
363144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            __ ucomisd(xmm1, xmm0);
363244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            __ j(above_equal, &slow);
363369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            __ cvttsd2si(ebx, Operand(xmm0));
363444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          }
363569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          // ebx: untagged integer value
363669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          __ mov(Operand(edi, ecx, times_2, 0), ebx);
36371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        }
363844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ ret(0);  // Return original value.
36391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
36401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
36411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
36421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Slow case: call runtime.
36441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&slow);
3645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Counters* counters = masm->isolate()->counters();
3646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->keyed_store_external_array_slow(), 1);
3647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
36481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ----------- S t a t e -------------
36491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- eax    : value
36501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- ecx    : key
36511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- edx    : receiver
36521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- esp[0] : return address
36531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
36541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow();
3656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(ic, RelocInfo::CODE_TARGET);
3657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- eax    : value
3660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ecx    : key
3661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- edx    : receiver
3662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- esp[0] : return address
3663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
3666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> miss_ic =
3667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
3673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- eax    : key
3675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- edx    : receiver
3676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- esp[0] : return address
3677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss_force_generic;
3679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
3681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
3682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is a smi.
36843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(eax, &miss_force_generic);
3685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the elements array.
3687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
3688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ AssertFastElements(ecx);
3689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is within bounds.
3691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset));
3692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(above_equal, &miss_force_generic);
3693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the result and make sure it's not the hole.
3695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(ebx, Operand(ecx, eax, times_2,
3696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      FixedArray::kHeaderSize - kHeapObjectTag));
3697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ cmp(ebx, masm->isolate()->factory()->the_hole_value());
3698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(equal, &miss_force_generic);
3699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(eax, ebx);
3700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ret(0);
3701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
3703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> miss_ic =
3704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
37093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(
37103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MacroAssembler* masm) {
37113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ----------- S t a t e -------------
37123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- eax    : key
37133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- edx    : receiver
37143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- esp[0] : return address
37153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
37163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label miss_force_generic, slow_allocate_heapnumber;
37173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
37193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // have been verified by the caller to not be a smi.
37203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is a smi.
37223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(eax, &miss_force_generic);
37233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Get the elements array.
37253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
37263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ AssertFastElements(ecx);
37273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is within bounds.
37293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmp(eax, FieldOperand(ecx, FixedDoubleArray::kLengthOffset));
37303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(above_equal, &miss_force_generic);
37313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check for the hole
37333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
37343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmp(FieldOperand(ecx, eax, times_4, offset), Immediate(kHoleNanUpper32));
37353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(equal, &miss_force_generic);
37363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Always allocate a heap number for the result.
37383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (CpuFeatures::IsSupported(SSE2)) {
37393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    CpuFeatures::Scope use_sse2(SSE2);
37403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ movdbl(xmm0, FieldOperand(ecx, eax, times_4,
37413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                 FixedDoubleArray::kHeaderSize));
37423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
37433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ fld_d(FieldOperand(ecx, eax, times_4, FixedDoubleArray::kHeaderSize));
37443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
37453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ AllocateHeapNumber(ecx, ebx, edi, &slow_allocate_heapnumber);
37463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Set the value.
37473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (CpuFeatures::IsSupported(SSE2)) {
37483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    CpuFeatures::Scope use_sse2(SSE2);
37493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ movdbl(FieldOperand(ecx, HeapNumber::kValueOffset), xmm0);
37503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
37513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ fstp_d(FieldOperand(ecx, HeapNumber::kValueOffset));
37523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
37533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(eax, ecx);
37543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ret(0);
37553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&slow_allocate_heapnumber);
37573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // A value was pushed on the floating point stack before the allocation, if
37583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // the allocation fails it needs to be removed.
37593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (!CpuFeatures::IsSupported(SSE2)) {
37603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ fstp(0);
37613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
37623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> slow_ic =
37633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_Slow();
37643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(slow_ic, RelocInfo::CODE_TARGET);
37653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&miss_force_generic);
37673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> miss_ic =
37683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
37693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
37703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
37713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastElement(
37743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MacroAssembler* masm,
37753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool is_js_array,
37763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKind elements_kind,
37773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    KeyedAccessGrowMode grow_mode) {
3778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
37793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- eax    : value
37803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- ecx    : key
3781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- edx    : receiver
3782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- esp[0] : return address
3783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
37843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label miss_force_generic, grow, slow, transition_elements_kind;
37853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label check_capacity, prepare_slow, finish_store, commit_backing_store;
3786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
3788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
3789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is a smi.
37913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(ecx, &miss_force_generic);
37921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
37933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
37943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfNotSmi(eax, &transition_elements_kind);
37953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
37963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the elements array and make sure it is a fast element array, not 'cow'.
3798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
3799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (is_js_array) {
3800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check that the key is within bounds.
3801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset));  // smis.
38023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (grow_mode == ALLOW_JSARRAY_GROWTH) {
38033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(above_equal, &grow);
38043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
38053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(above_equal, &miss_force_generic);
38063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
3808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check that the key is within bounds.
3809257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset));  // smis.
3810257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(above_equal, &miss_force_generic);
3811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
38133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(FieldOperand(edi, HeapObject::kMapOffset),
38143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         Immediate(masm->isolate()->factory()->fixed_array_map()));
38153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_equal, &miss_force_generic);
38163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&finish_store);
38183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
38193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // ecx is a smi, use times_half_pointer_size instead of
38203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // times_pointer_size
38213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(FieldOperand(edi,
38223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        ecx,
38233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        times_half_pointer_size,
38243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        FixedArray::kHeaderSize), eax);
38253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
38263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(elements_kind == FAST_ELEMENTS);
38273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Do the store and update the write barrier.
38283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // ecx is a smi, use times_half_pointer_size instead of
38293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // times_pointer_size
38303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lea(ecx, FieldOperand(edi,
38313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             ecx,
38323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             times_half_pointer_size,
38333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             FixedArray::kHeaderSize));
38343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(Operand(ecx, 0), eax);
38353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure to preserve the value in register eax.
38363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(ebx, eax);
38373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWrite(edi, ecx, ebx, kDontSaveFPRegs);
38383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3840257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Done.
3841257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ret(0);
38421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Handle store cache miss, replacing the ic with the generic stub.
3844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
3845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic_force_generic =
3846257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3847257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
38483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Handle transition to other elements kinds without using the generic stub.
38503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&transition_elements_kind);
38513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
38523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(ic_miss, RelocInfo::CODE_TARGET);
38533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
38553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Handle transition requiring the array to grow.
38563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&grow);
38573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure the array is only growing by a single element, anything else
38593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // must be handled by the runtime. Flags are already set by previous
38603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // compare.
38613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &miss_force_generic);
38623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for the empty array, and preallocate a small backing store if
38643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // possible.
38653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
38663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(edi, Immediate(masm->isolate()->factory()->empty_fixed_array()));
38673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &check_capacity);
38683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int size = FixedArray::SizeFor(JSArray::kPreallocatedArrayElements);
38703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ AllocateInNewSpace(size, edi, ebx, ecx, &prepare_slow, TAG_OBJECT);
38713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Restore the key, which is known to be the array length.
38723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // eax: value
38743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // ecx: key
38753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // edx: receiver
38763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // edi: elements
38773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure that the backing store can hold additional elements.
38783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(FieldOperand(edi, JSObject::kMapOffset),
38793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Immediate(masm->isolate()->factory()->fixed_array_map()));
38803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(FieldOperand(edi, FixedArray::kLengthOffset),
38813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Immediate(Smi::FromInt(JSArray::kPreallocatedArrayElements)));
38823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(ebx, Immediate(masm->isolate()->factory()->the_hole_value()));
38833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = 1; i < JSArray::kPreallocatedArrayElements; ++i) {
38843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(FieldOperand(edi, FixedArray::SizeFor(i)), ebx);
38853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
38863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Store the element at index zero.
38883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(FieldOperand(edi, FixedArray::SizeFor(0)), eax);
38893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Install the new backing store in the JSArray.
38913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(FieldOperand(edx, JSObject::kElementsOffset), edi);
38923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteField(edx, JSObject::kElementsOffset, edi, ebx,
38933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
38943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Increment the length of the array.
38963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(FieldOperand(edx, JSArray::kLengthOffset),
38973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Immediate(Smi::FromInt(1)));
38983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ret(0);
38993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&check_capacity);
39013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(FieldOperand(edi, HeapObject::kMapOffset),
39023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Immediate(masm->isolate()->factory()->fixed_cow_array_map()));
39033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(equal, &miss_force_generic);
39043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // eax: value
39063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // ecx: key
39073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // edx: receiver
39083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // edi: elements
39093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure that the backing store can hold additional elements.
39103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset));
39113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(above_equal, &slow);
39123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Grow the array and finish the store.
39143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(FieldOperand(edx, JSArray::kLengthOffset),
39153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Immediate(Smi::FromInt(1)));
39163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&finish_store);
39173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&prepare_slow);
39193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Restore the key, which is known to be the array length.
39203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(ecx, Immediate(0));
39213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&slow);
39233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
39243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(ic_slow, RelocInfo::CODE_TARGET);
39253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
39261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
39271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
39281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
39293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
39303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MacroAssembler* masm,
39313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool is_js_array,
39323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    KeyedAccessGrowMode grow_mode) {
39333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ----------- S t a t e -------------
39343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- eax    : value
39353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- ecx    : key
39363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- edx    : receiver
39373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- esp[0] : return address
39383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
39393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label miss_force_generic, transition_elements_kind, grow, slow;
39403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label check_capacity, prepare_slow, finish_store, commit_backing_store;
39413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
39423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
39433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // have been verified by the caller to not be a smi.
39443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
39453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is a smi.
39463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(ecx, &miss_force_generic);
39473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
39483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Get the elements array.
39493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
39503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ AssertFastElements(edi);
39513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
39523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (is_js_array) {
39533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Check that the key is within bounds.
39543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset));  // smis.
39553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (grow_mode == ALLOW_JSARRAY_GROWTH) {
39563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(above_equal, &grow);
39573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
39583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(above_equal, &miss_force_generic);
39593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
39603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
39613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Check that the key is within bounds.
39623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset));  // smis.
39633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(above_equal, &miss_force_generic);
396485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  }
396585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
39663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&finish_store);
39673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ StoreNumberToDoubleElements(eax, edi, ecx, edx, xmm0,
39683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 &transition_elements_kind, true);
39693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ret(0);
39703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
39713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Handle store cache miss, replacing the ic with the generic stub.
39723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&miss_force_generic);
39733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> ic_force_generic =
39743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
39753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
39763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Handle transition to other elements kinds without using the generic stub.
39783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&transition_elements_kind);
39793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
39803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(ic_miss, RelocInfo::CODE_TARGET);
39813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
39833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Handle transition requiring the array to grow.
39843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&grow);
39853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure the array is only growing by a single element, anything else
39873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // must be handled by the runtime. Flags are already set by previous
39883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // compare.
39893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &miss_force_generic);
39903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Transition on values that can't be stored in a FixedDoubleArray.
39923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label value_is_smi;
39933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfSmi(eax, &value_is_smi);
39943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
39953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Immediate(Handle<Map>(masm->isolate()->heap()->heap_number_map())));
39963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &transition_elements_kind);
39973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&value_is_smi);
39983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for the empty array, and preallocate a small backing store if
40003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // possible.
40013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
40023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(edi, Immediate(masm->isolate()->factory()->empty_fixed_array()));
40033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &check_capacity);
40043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int size = FixedDoubleArray::SizeFor(JSArray::kPreallocatedArrayElements);
40063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ AllocateInNewSpace(size, edi, ebx, ecx, &prepare_slow, TAG_OBJECT);
40073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Restore the key, which is known to be the array length.
40083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(ecx, Immediate(0));
40093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // eax: value
40113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // ecx: key
40123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // edx: receiver
40133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // edi: elements
40143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Initialize the new FixedDoubleArray. Leave elements unitialized for
40153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // efficiency, they are guaranteed to be initialized before use.
40163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(FieldOperand(edi, JSObject::kMapOffset),
40173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Immediate(masm->isolate()->factory()->fixed_double_array_map()));
40183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(FieldOperand(edi, FixedDoubleArray::kLengthOffset),
40193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Immediate(Smi::FromInt(JSArray::kPreallocatedArrayElements)));
40203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Install the new backing store in the JSArray.
40223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(FieldOperand(edx, JSObject::kElementsOffset), edi);
40233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteField(edx, JSObject::kElementsOffset, edi, ebx,
40243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
40253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Increment the length of the array.
40273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(FieldOperand(edx, JSArray::kLengthOffset),
40283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Immediate(Smi::FromInt(1)));
40293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
40303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&finish_store);
40313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&check_capacity);
40333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // eax: value
40343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // ecx: key
40353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // edx: receiver
40363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // edi: elements
40373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure that the backing store can hold additional elements.
40383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(ecx, FieldOperand(edi, FixedDoubleArray::kLengthOffset));
40393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(above_equal, &slow);
40403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Grow the array and finish the store.
40423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(FieldOperand(edx, JSArray::kLengthOffset),
40433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Immediate(Smi::FromInt(1)));
40443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&finish_store);
40453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&prepare_slow);
40473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Restore the key, which is known to be the array length.
40483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(ecx, Immediate(0));
40493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&slow);
40513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
40523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(ic_slow, RelocInfo::CODE_TARGET);
40533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
40543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
40553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
40563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __
4058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
4060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
4061f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_IA32
4062