stub-cache-ia32.cc revision 3ef787dbeca8a5fb1086949cda830dccee07bfbd
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.
7493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(receiver_reg, Handle<Map>(object->map()),
7503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              miss_label, DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform global security token check if needed.
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsJSGlobalProxy()) {
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub never generated for non-global objects that require access
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // checks.
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform map transition for the receiver if necessary.
7623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) {
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The properties must be extended before we can store the value.
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // We jump to a runtime call that extends the properties array.
765402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ pop(scratch);  // Return address.
766402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ push(receiver_reg);
7673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(Immediate(transition));
768402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ push(eax);
769402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ push(scratch);
7706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ TailCallExternalReference(
77144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
77244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          masm->isolate()),
77344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        3,
77444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        1);
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!transition.is_null()) {
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Update the map of the object; no write barrier updating is
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // needed because the map is never in new space.
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset),
7823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Immediate(transition));
783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Adjust for the number of properties stored in the object. Even in the
786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // face of a transition we can use the old map here because the size of the
787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object and the number of in-object properties is not going to change.
788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  index -= object->map()->inobject_properties();
789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (index < 0) {
791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Set the property straight into the object.
792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = object->map()->instance_size() + (index * kPointerSize);
793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(FieldOperand(receiver_reg, offset), eax);
794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Update the write barrier for the array address.
796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Pass the value being stored in the now unused name_reg.
7973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(name_reg, eax);
7983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteField(receiver_reg,
7993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        offset,
8003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        name_reg,
8013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        scratch,
8023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        kDontSaveFPRegs);
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Write to the properties array.
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = index * kPointerSize + FixedArray::kHeaderSize;
806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Get the properties array (optimistically).
807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(FieldOperand(scratch, offset), eax);
809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Update the write barrier for the array address.
811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Pass the value being stored in the now unused name_reg.
8123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(name_reg, eax);
8133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteField(scratch,
8143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        offset,
8153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        name_reg,
8163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        receiver_reg,
8173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        kDontSaveFPRegs);
818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the value (register eax).
821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Generate code to check that a global property cell is empty. Create
8266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// the property cell at compilation time if no cell exists for the
8276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// property.
8283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateCheckPropertyCell(MacroAssembler* masm,
8293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Handle<GlobalObject> global,
8303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Handle<String> name,
8313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Register scratch,
8323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      Label* miss) {
8333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSGlobalPropertyCell> cell =
8343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GlobalObject::EnsurePropertyCell(global, name);
8356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(cell->value()->IsTheHole());
8363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Oddball> the_hole = masm->isolate()->factory()->the_hole_value();
837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (Serializer::enabled()) {
8383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(scratch, Immediate(cell));
839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset),
8403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Immediate(the_hole));
841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
8423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(Operand::Cell(cell), Immediate(the_hole));
843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, miss);
8456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
8466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8488defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Calls GenerateCheckPropertyCell for each global object in the prototype chain
8498defd9ff6930b4e24729971a61cf7469daf119beSteve Block// from object to (but not including) holder.
8503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateCheckPropertyCells(MacroAssembler* masm,
8513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Handle<JSObject> object,
8523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Handle<JSObject> holder,
8533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Handle<String> name,
8543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Register scratch,
8553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Label* miss) {
8563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSObject> current = object;
8573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while (!current.is_identical_to(holder)) {
8588defd9ff6930b4e24729971a61cf7469daf119beSteve Block    if (current->IsGlobalObject()) {
8593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GenerateCheckPropertyCell(masm,
8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                Handle<GlobalObject>::cast(current),
8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                name,
8623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                scratch,
8633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                miss);
8648defd9ff6930b4e24729971a61cf7469daf119beSteve Block    }
8653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    current = Handle<JSObject>(JSObject::cast(current->GetPrototype()));
8668defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
8678defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
8688defd9ff6930b4e24729971a61cf7469daf119beSteve Block
869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __
870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm())
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8733ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochRegister StubCompiler::CheckPrototypes(Handle<JSObject> object,
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       Register object_reg,
8753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Handle<JSObject> holder,
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       Register holder_reg,
8773bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       Register scratch1,
8783bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       Register scratch2,
8793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Handle<String> name,
8808defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                       int save_at_depth,
8813bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                       Label* miss) {
8828defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Make sure there's no overlap between holder and object registers.
8833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
8843bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
8853bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch         && !scratch2.is(scratch1));
88644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
8878defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Keep track of the current object in register reg.
8888defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Register reg = object_reg;
8893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSObject> current = object;
8908defd9ff6930b4e24729971a61cf7469daf119beSteve Block  int depth = 0;
8918defd9ff6930b4e24729971a61cf7469daf119beSteve Block
8928defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (save_at_depth == depth) {
8938defd9ff6930b4e24729971a61cf7469daf119beSteve Block    __ mov(Operand(esp, kPointerSize), reg);
8948defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8968defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Traverse the prototype chain and check the maps in the prototype chain for
8978defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // fast and global objects or do negative lookup for normal objects.
8983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while (!current.is_identical_to(holder)) {
8993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ++depth;
9008defd9ff6930b4e24729971a61cf7469daf119beSteve Block
9018defd9ff6930b4e24729971a61cf7469daf119beSteve Block    // Only global objects and objects that do not require access
9028defd9ff6930b4e24729971a61cf7469daf119beSteve Block    // checks are allowed in stubs.
9038defd9ff6930b4e24729971a61cf7469daf119beSteve Block    ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
9048defd9ff6930b4e24729971a61cf7469daf119beSteve Block
9053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> prototype(JSObject::cast(current->GetPrototype()));
9068defd9ff6930b4e24729971a61cf7469daf119beSteve Block    if (!current->HasFastProperties() &&
9078defd9ff6930b4e24729971a61cf7469daf119beSteve Block        !current->IsJSGlobalObject() &&
9088defd9ff6930b4e24729971a61cf7469daf119beSteve Block        !current->IsJSGlobalProxy()) {
9098defd9ff6930b4e24729971a61cf7469daf119beSteve Block      if (!name->IsSymbol()) {
9103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        name = factory()->LookupSymbol(name);
9118defd9ff6930b4e24729971a61cf7469daf119beSteve Block      }
9123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(current->property_dictionary()->FindEntry(*name) ==
9138defd9ff6930b4e24729971a61cf7469daf119beSteve Block             StringDictionary::kNotFound);
9148defd9ff6930b4e24729971a61cf7469daf119beSteve Block
9153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GenerateDictionaryNegativeLookup(masm(), miss, reg, name,
9163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       scratch1, scratch2);
917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
9183bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
9193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      reg = holder_reg;  // From now on the object will be in holder_reg.
9203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
9213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
9223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      bool in_new_space = heap()->InNewSpace(*prototype);
9233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Map> current_map(current->map());
9243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (in_new_space) {
9253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Save the map in scratch1 for later.
9263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch        __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
9278defd9ff6930b4e24729971a61cf7469daf119beSteve Block      }
9283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK,
9293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  ALLOW_ELEMENT_TRANSITION_MAPS);
9303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check access rights to the global object.  This has to happen after
9323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // the map check so that we know that the object is actually a global
9333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // object.
9348defd9ff6930b4e24729971a61cf7469daf119beSteve Block      if (current->IsJSGlobalProxy()) {
9353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CheckAccessGlobalProxy(reg, scratch2, miss);
9363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
9373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      reg = holder_reg;  // From now on the object will be in holder_reg.
9383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (in_new_space) {
9403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // The prototype is in new space; we cannot store a reference to it
9413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // in the code.  Load it from the map.
9423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
9433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
9443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // The prototype is in old space; load it directly.
9453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ mov(reg, prototype);
946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
9488defd9ff6930b4e24729971a61cf7469daf119beSteve Block
9498defd9ff6930b4e24729971a61cf7469daf119beSteve Block    if (save_at_depth == depth) {
9508defd9ff6930b4e24729971a61cf7469daf119beSteve Block      __ mov(Operand(esp, kPointerSize), reg);
9518defd9ff6930b4e24729971a61cf7469daf119beSteve Block    }
9528defd9ff6930b4e24729971a61cf7469daf119beSteve Block
9538defd9ff6930b4e24729971a61cf7469daf119beSteve Block    // Go to the next object in the prototype chain.
9548defd9ff6930b4e24729971a61cf7469daf119beSteve Block    current = prototype;
955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
9563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(current.is_identical_to(holder));
9578defd9ff6930b4e24729971a61cf7469daf119beSteve Block
9588defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Log the check depth.
95944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
9608defd9ff6930b4e24729971a61cf7469daf119beSteve Block
9618defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Check the holder map.
9623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(reg, Handle<Map>(holder->map()),
9633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              miss, DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
9648defd9ff6930b4e24729971a61cf7469daf119beSteve Block
9658defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Perform security check for access to the global object.
9668defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
9678defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (holder->IsJSGlobalProxy()) {
9683bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    __ CheckAccessGlobalProxy(reg, scratch1, miss);
9693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
9703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If we've skipped any global objects, it's not enough to verify that
9723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // their maps haven't changed.  We also need to check that the property
9733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // cell for the property is still empty.
9743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss);
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
976402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Return the register containing the holder.
9778defd9ff6930b4e24729971a61cf7469daf119beSteve Block  return reg;
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadField(Handle<JSObject> object,
9823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Handle<JSObject> holder,
983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Register receiver,
984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Register scratch1,
985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Register scratch2,
9863bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                     Register scratch3,
987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     int index,
9883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Handle<String> name,
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     Label* miss) {
990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
9913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver, miss);
992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the prototype chain.
9943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register reg = CheckPrototypes(
9953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the value from the properties.
998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateFastPropertyLoad(masm(), eax, reg, holder, index);
999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadCallback(Handle<JSObject> object,
10043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<JSObject> holder,
10053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Register receiver,
10063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Register name_reg,
10073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Register scratch1,
10083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Register scratch2,
10093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Register scratch3,
10103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<AccessorInfo> callback,
10113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<String> name,
10123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Label* miss) {
1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
10143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver, miss);
1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the maps haven't changed.
10173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register reg = CheckPrototypes(object, receiver, holder, scratch1,
10183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 scratch2, scratch3, name, miss);
1019d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
10208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Insert additional parameters into the stack frame above return address.
10218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ASSERT(!scratch3.is(reg));
10228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ pop(scratch3);  // Get return address to place it below.
10238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(receiver);  // receiver
10253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(scratch2, esp);
10268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ASSERT(!scratch2.is(reg));
1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(reg);  // holder
10289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Push data from AccessorInfo.
10293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (isolate()->heap()->InNewSpace(callback->data())) {
10303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(scratch1, Immediate(callback));
10318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset));
10329dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  } else {
10333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(Immediate(Handle<Object>(callback->data())));
10349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
10358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1036d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Save a pointer to where we pushed the arguments pointer.
10376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // This will be passed as the const AccessorInfo& to the C++ callback.
10388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ push(scratch2);
10398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
10408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ push(name_reg);  // name
10418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(ebx, esp);  // esp points to reference to name (handler).
10428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
10438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ push(scratch3);  // Restore return address.
1044d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
10453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // 3 elements array for v8::Arguments::values_, handler for name and pointer
10468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // to the values (it considered as smi in GC).
10478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const int kStackSpace = 5;
10488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const int kApiArgc = 2;
10498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
10503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ PrepareCallApiFunction(kApiArgc);
10518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(ApiParameterOperand(0), ebx);  // name.
10523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(ebx, Immediate(kPointerSize));
10538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(ApiParameterOperand(1), ebx);  // arguments pointer.
10548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1055e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emitting a stub call may try to allocate (if the code is not
1056e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // already generated).  Do not allow the assembler to perform a
1057e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // garbage collection but instead return the allocation failure
1058e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // object.
10593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address getter_address = v8::ToCData<Address>(callback->getter());
10603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallApiFunctionAndReturn(getter_address, kStackSpace);
1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadConstant(Handle<JSObject> object,
10653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<JSObject> holder,
1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register receiver,
1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch1,
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Register scratch2,
10693bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                        Register scratch3,
10703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<JSFunction> value,
10713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<String> name,
1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Label* miss) {
1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
10743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver, miss);
1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the maps haven't changed.
10773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(
10783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the constant value.
10813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadHeapObject(eax, value);
1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object,
10873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           Handle<JSObject> interceptor_holder,
1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           LookupResult* lookup,
1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register receiver,
1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register name_reg,
1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register scratch1,
1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Register scratch2,
10933bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                           Register scratch3,
10943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           Handle<String> name,
1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Label* miss) {
10967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(interceptor_holder->HasNamedInterceptor());
10977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
10987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
10997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Check that the receiver isn't a smi.
11003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver, miss);
11017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // So far the most popular follow ups for interceptor loads are FIELD
11037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // and CALLBACKS, so inline only them, other cases may be added
11047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // later.
11057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  bool compile_followup_inline = false;
11063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (lookup->IsFound() && lookup->IsCacheable()) {
11077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    if (lookup->type() == FIELD) {
11087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      compile_followup_inline = true;
11097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    } else if (lookup->type() == CALLBACKS &&
11103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               lookup->GetCallbackObject()->IsAccessorInfo()) {
11113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      compile_followup_inline =
11123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL;
11137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
11147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
11157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (compile_followup_inline) {
11177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Compile the interceptor call, followed by inline code to load the
11187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // property from further up the prototype chain if the call fails.
11197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Check that the maps haven't changed.
11207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
11213bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                          scratch1, scratch2, scratch3,
11223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                          name, miss);
11237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1));
11247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Save necessary data before invoking an interceptor.
11267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Requires a frame to make GC aware of pushed pointers.
11273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    {
11283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FrameScope frame_scope(masm(), StackFrame::INTERNAL);
11297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
11313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // CALLBACKS case needs a receiver to be passed into C++ callback.
11323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ push(receiver);
11333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
11343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ push(holder_reg);
11353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ push(name_reg);
1136592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
11373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Invoke an interceptor.  Note: map checks from receiver to
11383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // interceptor's holder has been compiled before (see a caller
11393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // of this method.)
11403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CompileCallLoadPropertyWithInterceptor(masm(),
11413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             receiver,
11423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             holder_reg,
11433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             name_reg,
11443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             interceptor_holder);
11453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check if interceptor provided a value for property.  If it's
11473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // the case, return immediately.
11483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label interceptor_failed;
11493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ cmp(eax, factory()->no_interceptor_result_sentinel());
11503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(equal, &interceptor_failed);
11513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      frame_scope.GenerateLeaveFrame();
11523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ret(0);
11537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&interceptor_failed);
11553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(name_reg);
11563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(holder_reg);
11573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
11583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ pop(receiver);
11593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
11603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Leave the internal frame.
11623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
116385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
11647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Check that the maps from interceptor's holder to lookup's holder
11657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // haven't changed.  And load lookup's holder into holder_reg.
11663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (*interceptor_holder != lookup->holder()) {
11677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      holder_reg = CheckPrototypes(interceptor_holder,
11687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   holder_reg,
11693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Handle<JSObject>(lookup->holder()),
11707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   scratch1,
11717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   scratch2,
11723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                   scratch3,
11737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   name,
11747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   miss);
11757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
11767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    if (lookup->type() == FIELD) {
11787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // We found FIELD property in prototype chain of interceptor's holder.
11797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Retrieve a field from field's holder.
11807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      GenerateFastPropertyLoad(masm(), eax, holder_reg,
11813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Handle<JSObject>(lookup->holder()),
11823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               lookup->GetFieldIndex());
11837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ ret(0);
11847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    } else {
11857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // We found CALLBACKS property in prototype chain of interceptor's
11867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // holder.
11877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ASSERT(lookup->type() == CALLBACKS);
11883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<AccessorInfo> callback(
11893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AccessorInfo::cast(lookup->GetCallbackObject()));
11907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ASSERT(callback->getter() != NULL);
11917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Tail call to runtime.
11937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Important invariant in CALLBACKS case: the code above must be
11947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // structured to never clobber |receiver| register.
11957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ pop(scratch2);  // return address
11967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(receiver);
11977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(holder_reg);
11983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(holder_reg, Immediate(callback));
11997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset));
12008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      __ push(holder_reg);
12017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(name_reg);
12027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ push(scratch2);  // restore return address
12037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      ExternalReference ref =
120544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ExternalReference(IC_Utility(IC::kLoadCallbackProperty),
120644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            masm()->isolate());
12077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ TailCallExternalReference(ref, 5, 1);
12087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
12097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  } else {  // !compile_followup_inline
12107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Call the runtime system to load the interceptor.
12117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // Check that the maps haven't changed.
12127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    Register holder_reg =
12137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        CheckPrototypes(object, receiver, interceptor_holder,
12143bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                        scratch1, scratch2, scratch3, name, miss);
12157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ pop(scratch2);  // save old return address
12167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    PushInterceptorArguments(masm(), receiver, holder_reg,
12177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                             name_reg, interceptor_holder);
12187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ push(scratch2);  // restore old return address
12197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
122044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ExternalReference ref =
122144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad),
122244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          isolate());
12237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ TailCallExternalReference(ref, 5, 1);
12247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) {
12297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (kind_ == Code::KEYED_CALL_IC) {
12303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(ecx, Immediate(name));
1231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(not_equal, miss);
12327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
12337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
12347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
12373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSObject> holder,
12383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<String> name,
123959151504615d929945dc59db37bf1166937748c6Steve Block                                                   Label* miss) {
124059151504615d929945dc59db37bf1166937748c6Steve Block  ASSERT(holder->IsGlobalObject());
124159151504615d929945dc59db37bf1166937748c6Steve Block
124259151504615d929945dc59db37bf1166937748c6Steve Block  // Get the number of arguments.
124359151504615d929945dc59db37bf1166937748c6Steve Block  const int argc = arguments().immediate();
124459151504615d929945dc59db37bf1166937748c6Steve Block
124559151504615d929945dc59db37bf1166937748c6Steve Block  // Get the receiver from the stack.
124659151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
124759151504615d929945dc59db37bf1166937748c6Steve Block
124859151504615d929945dc59db37bf1166937748c6Steve Block
124959151504615d929945dc59db37bf1166937748c6Steve Block  // Check that the maps haven't changed.
12503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(edx, miss);
125159151504615d929945dc59db37bf1166937748c6Steve Block  CheckPrototypes(object, edx, holder, ebx, eax, edi, name, miss);
125259151504615d929945dc59db37bf1166937748c6Steve Block}
125359151504615d929945dc59db37bf1166937748c6Steve Block
125459151504615d929945dc59db37bf1166937748c6Steve Block
12553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateLoadFunctionFromCell(
12563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
12573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
12583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label* miss) {
125959151504615d929945dc59db37bf1166937748c6Steve Block  // Get the value from the cell.
1260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (Serializer::enabled()) {
12613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(edi, Immediate(cell));
1262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset));
1263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
12643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(edi, Operand::Cell(cell));
1265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
126659151504615d929945dc59db37bf1166937748c6Steve Block
126759151504615d929945dc59db37bf1166937748c6Steve Block  // Check that the cell contains the same function.
12683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (isolate()->heap()->InNewSpace(*function)) {
126959151504615d929945dc59db37bf1166937748c6Steve Block    // We can't embed a pointer to a function in new space so we have
127059151504615d929945dc59db37bf1166937748c6Steve Block    // to verify that the shared function info is unchanged. This has
127159151504615d929945dc59db37bf1166937748c6Steve Block    // the nice side effect that multiple closures based on the same
127259151504615d929945dc59db37bf1166937748c6Steve Block    // function can all use this call IC. Before we load through the
127359151504615d929945dc59db37bf1166937748c6Steve Block    // function, we have to verify that it still is a function.
12743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(edi, miss);
127559151504615d929945dc59db37bf1166937748c6Steve Block    __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
1276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(not_equal, miss);
127759151504615d929945dc59db37bf1166937748c6Steve Block
127859151504615d929945dc59db37bf1166937748c6Steve Block    // Check the shared function info. Make sure it hasn't changed.
127959151504615d929945dc59db37bf1166937748c6Steve Block    __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset),
128059151504615d929945dc59db37bf1166937748c6Steve Block           Immediate(Handle<SharedFunctionInfo>(function->shared())));
128159151504615d929945dc59db37bf1166937748c6Steve Block  } else {
12823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(edi, Immediate(function));
128359151504615d929945dc59db37bf1166937748c6Steve Block  }
12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_equal, miss);
128559151504615d929945dc59db37bf1166937748c6Steve Block}
128659151504615d929945dc59db37bf1166937748c6Steve Block
128759151504615d929945dc59db37bf1166937748c6Steve Block
12883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateMissBranch() {
12893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> code =
129044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
1291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                               kind_,
12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               extra_state_);
12933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(code, RelocInfo::CODE_TARGET);
12947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
12957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12973ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
12983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<JSObject> holder,
12993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                int index,
13003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<String> name) {
1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ecx                 : name
1303e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[0]              : return address
1304e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
1305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ...
1306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc + 1) * 4] : receiver
1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateNameCheck(name, &miss);
13117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver from the stack.
1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
13173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(edx, &miss);
1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do the right check and compute the holder register.
13203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  Register reg = CheckPrototypes(object, edx, holder, ebx, eax, edi,
13213bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch                                 name, &miss);
1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateFastPropertyLoad(masm(), edi, reg, holder, index);
1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the function really is a function.
13263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(edi, &miss);
1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
1328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the receiver on the stack with the global proxy if
1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // necessary.
1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsGlobalObject()) {
1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the function.
13383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
1339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
1340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
1341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
1342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), call_kind);
1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
13463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(FIELD, name);
1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13533ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPushCall(
13543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
13553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
13563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
13573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
13583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
13596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
13606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ecx                 : name
13616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- esp[0]              : return address
13626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
13636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ...
13646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- esp[(argc + 1) * 4] : receiver
13656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
13666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // If object is not an array, bail out to regular call.
13683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSArray() || !cell.is_null()) {
13693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Handle<Code>::null();
137044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
13716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss;
13736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateNameCheck(name, &miss);
13757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the receiver from the stack.
13776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int argc = arguments().immediate();
13786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
13796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the receiver isn't a smi.
13813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(edx, &miss);
13826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
13843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  name, &miss);
13856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (argc == 0) {
13876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Noop, return the length.
13886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
13896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ ret((argc + 1) * kPointerSize);
13906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
1391756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Label call_builtin;
1392756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
13933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (argc == 1) {  // Otherwise fall through to call builtin.
13943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label attempt_to_grow_elements, with_write_barrier;
13956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Get the elements array of the object.
13973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(edi, FieldOperand(edx, JSArray::kElementsOffset));
13985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
13993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check that the elements are in fast mode and writable.
14003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ cmp(FieldOperand(edi, HeapObject::kMapOffset),
14013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             Immediate(factory()->fixed_array_map()));
14023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(not_equal, &call_builtin);
14035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
14046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Get the array's length into eax and calculate new length.
14056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
14066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      STATIC_ASSERT(kSmiTagSize == 1);
14076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      STATIC_ASSERT(kSmiTag == 0);
14083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ add(eax, Immediate(Smi::FromInt(argc)));
14096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Get the elements' length into ecx.
14113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(ecx, FieldOperand(edi, FixedArray::kLengthOffset));
14126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Check if we could survive without allocation.
14143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ cmp(eax, ecx);
14156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ j(greater, &attempt_to_grow_elements);
14166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check if value is a smi.
14183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(ecx, Operand(esp, argc * kPointerSize));
14193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ JumpIfNotSmi(ecx, &with_write_barrier);
14203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Save new length.
14226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
14236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Store the value.
14253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(FieldOperand(edi,
14263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          eax,
14273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          times_half_pointer_size,
14283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          FixedArray::kHeaderSize - argc * kPointerSize),
14293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             ecx);
143085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
14316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ ret((argc + 1) * kPointerSize);
14326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      __ bind(&with_write_barrier);
14346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
14363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (FLAG_smi_only_arrays  && !FLAG_trace_elements_transitions) {
14383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Label fast_object, not_fast_object;
14393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CheckFastObjectElements(ebx, &not_fast_object, Label::kNear);
14403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ jmp(&fast_object);
14413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // In case of fast smi-only, convert to fast object, otherwise bail out.
14423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&not_fast_object);
14433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CheckFastSmiOnlyElements(ebx, &call_builtin);
14443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // edi: elements array
14453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // edx: receiver
14463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // ebx: map
14473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS,
14483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               FAST_ELEMENTS,
14493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               ebx,
14503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               edi,
14513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               &call_builtin);
14523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ElementsTransitionGenerator::GenerateSmiOnlyToObject(masm());
14533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Restore edi.
14543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ mov(edi, FieldOperand(edx, JSArray::kElementsOffset));
14553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&fast_object);
14563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
14573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CheckFastObjectElements(ebx, &call_builtin);
14583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
14593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Save new length.
14613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
14623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Store the value.
14643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lea(edx, FieldOperand(edi,
14653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               eax, times_half_pointer_size,
14663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               FixedArray::kHeaderSize - argc * kPointerSize));
14673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(Operand(edx, 0), ecx);
14683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ RecordWrite(edi, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
14703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     OMIT_SMI_CHECK);
14716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ ret((argc + 1) * kPointerSize);
14736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ bind(&attempt_to_grow_elements);
14755913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      if (!FLAG_inline_new) {
14765913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        __ jmp(&call_builtin);
14775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      }
14785913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck
14793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(ebx, Operand(esp, argc * kPointerSize));
14803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Growing elements that are SMI-only requires special handling in case
14813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // the new element is non-Smi. For now, delegate to the builtin.
14823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label no_fast_elements_check;
14833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ JumpIfSmi(ebx, &no_fast_elements_check);
14843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
14853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CheckFastObjectElements(ecx, &call_builtin, Label::kFar);
14863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&no_fast_elements_check);
14873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // We could be lucky and the elements array could be at the top of
14893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // new-space.  In this case we can just grow it in place by moving the
14903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // allocation pointer up.
14913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ExternalReference new_space_allocation_top =
149344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ExternalReference::new_space_allocation_top_address(isolate());
14946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ExternalReference new_space_allocation_limit =
149544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ExternalReference::new_space_allocation_limit_address(isolate());
14966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      const int kAllocationDelta = 4;
14986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Load top.
14996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ mov(ecx, Operand::StaticVariable(new_space_allocation_top));
15006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Check if it's the end of elements.
15023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lea(edx, FieldOperand(edi,
15036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               eax, times_half_pointer_size,
15046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               FixedArray::kHeaderSize - argc * kPointerSize));
15053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ cmp(edx, ecx);
15066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ j(not_equal, &call_builtin);
15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ add(ecx, Immediate(kAllocationDelta * kPointerSize));
15086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ cmp(ecx, Operand::StaticVariable(new_space_allocation_limit));
15096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ j(above, &call_builtin);
15106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // We fit and could grow elements.
15126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ mov(Operand::StaticVariable(new_space_allocation_top), ecx);
15136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Push the argument...
15153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(Operand(edx, 0), ebx);
15166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // ... and fill the rest with holes.
15176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      for (int i = 1; i < kAllocationDelta; i++) {
15186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        __ mov(Operand(edx, i * kPointerSize),
151944f0eee88ff00398ff7f715fab053374d808c90dSteve Block               Immediate(factory()->the_hole_value()));
15206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
15216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // We know the elements array is in new space so we don't need the
15233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // remembered set, but we just pushed a value onto it so we may have to
15243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // tell the incremental marker to rescan the object that we just grew.  We
15253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // don't need to worry about the holes because they are in old space and
15263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // already marked black.
15273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ RecordWrite(edi, edx, ebx, kDontSaveFPRegs, OMIT_REMEMBERED_SET);
15283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Restore receiver to edx as finish sequence assumes it's here.
15306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
15316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Increment element's and array's sizes.
15333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ add(FieldOperand(edi, FixedArray::kLengthOffset),
15347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch             Immediate(Smi::FromInt(kAllocationDelta)));
15353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // NOTE: This only happen in new-space, where we don't
15373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // care about the black-byte-count on pages. Otherwise we should
15383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // update that too if the object is black.
15393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
15416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ ret((argc + 1) * kPointerSize);
15436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
15446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1545756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ bind(&call_builtin);
154644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ TailCallExternalReference(
154744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ExternalReference(Builtins::c_ArrayPush, isolate()),
154844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        argc + 1,
154944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        1);
15506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
15516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss);
15533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
15546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return the generated code.
155625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  return GetCode(function);
15576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
15586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15603ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPopCall(
15613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
15623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
15633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
15643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
15653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
15666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
15676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ecx                 : name
15686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- esp[0]              : return address
15696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
15706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ...
15716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- esp[(argc + 1) * 4] : receiver
15726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
15736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // If object is not an array, bail out to regular call.
15753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSArray() || !cell.is_null()) {
15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Handle<Code>::null();
157744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
15786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss, return_undefined, call_builtin;
15806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateNameCheck(name, &miss);
15827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
15836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the receiver from the stack.
15846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int argc = arguments().immediate();
15856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
15866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the receiver isn't a smi.
15883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(edx, &miss);
15893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
15903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  name, &miss);
15916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the elements array of the object.
15936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset));
15946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1595756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Check that the elements are in fast mode and writable.
15966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
159744f0eee88ff00398ff7f715fab053374d808c90dSteve Block         Immediate(factory()->fixed_array_map()));
1598756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ j(not_equal, &call_builtin);
15996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the array's length into ecx and calculate new length.
16016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(ecx, FieldOperand(edx, JSArray::kLengthOffset));
16023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sub(ecx, Immediate(Smi::FromInt(1)));
16036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ j(negative, &return_undefined);
16046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the last element.
16066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  STATIC_ASSERT(kSmiTagSize == 1);
16076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  STATIC_ASSERT(kSmiTag == 0);
16086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(eax, FieldOperand(ebx,
16096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           ecx, times_half_pointer_size,
16106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           FixedArray::kHeaderSize));
16113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(eax, Immediate(factory()->the_hole_value()));
16126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ j(equal, &call_builtin);
16136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Set the array's length.
16156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(FieldOperand(edx, JSArray::kLengthOffset), ecx);
16166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Fill with the hole.
16186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(FieldOperand(ebx,
16196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      ecx, times_half_pointer_size,
16206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      FixedArray::kHeaderSize),
162144f0eee88ff00398ff7f715fab053374d808c90dSteve Block         Immediate(factory()->the_hole_value()));
16226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ret((argc + 1) * kPointerSize);
16236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&return_undefined);
162544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(eax, Immediate(factory()->undefined_value()));
16266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ret((argc + 1) * kPointerSize);
16276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&call_builtin);
162944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ TailCallExternalReference(
163044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(Builtins::c_ArrayPop, isolate()),
163144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      argc + 1,
163244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      1);
16336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss);
16353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
16367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
16377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Return the generated code.
16387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  return GetCode(function);
16397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
16407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
16417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
16423ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
16433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
16443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
16453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
16463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
16473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
16487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // ----------- S t a t e -------------
16497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- ecx                 : function name
16507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[0]              : return address
16517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
16527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- ...
16537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[(argc + 1) * 4] : receiver
16547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // -----------------------------------
16557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1656756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // If object is not a string, bail out to regular call.
16573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsString() || !cell.is_null()) {
16583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Handle<Code>::null();
165944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1660756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
16617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  const int argc = arguments().immediate();
16627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
16637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label miss;
1664b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label name_miss;
16657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
1666b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label* index_out_of_range_label = &index_out_of_range;
16679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
1668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (kind_ == Code::CALL_IC &&
16693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      (CallICBase::StringStubState::decode(extra_state_) ==
1670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       DEFAULT_STRING_STUB)) {
1671b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    index_out_of_range_label = &miss;
1672b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1673b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1674b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  GenerateNameCheck(name, &name_miss);
16757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
16767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Check that the maps starting from the prototype haven't changed.
16777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateDirectLoadGlobalFunctionPrototype(masm(),
16787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                            Context::STRING_FUNCTION_INDEX,
16790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            eax,
16800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            &miss);
16813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!object.is_identical_to(holder));
16823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())),
16833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  eax, holder, ebx, edx, edi, name, &miss);
16847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
16857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register receiver = ebx;
16867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = edi;
16877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = eax;
16887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize));
16897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (argc > 0) {
16907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ mov(index, Operand(esp, (argc - 0) * kPointerSize));
16917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  } else {
169244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ Set(index, Immediate(factory()->undefined_value()));
16937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
16947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
16953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringCharCodeAtGenerator generator(receiver,
16963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      index,
16973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      result,
16983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      &miss,  // When not a string.
16993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      &miss,  // When not a number.
17003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      index_out_of_range_label,
17013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      STRING_INDEX_IS_NUMBER);
17023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateFast(masm());
17037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ ret((argc + 1) * kPointerSize);
17047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StubRuntimeCallHelper call_helper;
17063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateSlow(masm(), call_helper);
17077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1708b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (index_out_of_range.is_linked()) {
1709b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ bind(&index_out_of_range);
171044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ Set(eax, Immediate(factory()->nan_value()));
1711b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ ret((argc + 1) * kPointerSize);
1712b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
17137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
17147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&miss);
1715b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Restore function name in ecx.
17163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Set(ecx, Immediate(name));
1717b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&name_miss);
17183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
17197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
17207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Return the generated code.
17217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  return GetCode(function);
17227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
17237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
17247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
17253ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharAtCall(
17263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
17273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
17283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
17293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
17303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
17317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // ----------- S t a t e -------------
17327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- ecx                 : function name
17337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[0]              : return address
17347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
17357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- ...
17367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[(argc + 1) * 4] : receiver
17377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // -----------------------------------
17387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1739756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // If object is not a string, bail out to regular call.
17403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsString() || !cell.is_null()) {
17413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Handle<Code>::null();
174244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
1743756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
17447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  const int argc = arguments().immediate();
17457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
17467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label miss;
1747b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label name_miss;
17487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_out_of_range;
1749b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Label* index_out_of_range_label = &index_out_of_range;
17507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (kind_ == Code::CALL_IC &&
17523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      (CallICBase::StringStubState::decode(extra_state_) ==
1753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch       DEFAULT_STRING_STUB)) {
1754b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    index_out_of_range_label = &miss;
1755b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1756b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1757b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  GenerateNameCheck(name, &name_miss);
17587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
17597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Check that the maps starting from the prototype haven't changed.
17607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateDirectLoadGlobalFunctionPrototype(masm(),
17617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                            Context::STRING_FUNCTION_INDEX,
17620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            eax,
17630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                            &miss);
17643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!object.is_identical_to(holder));
17653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())),
17663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  eax, holder, ebx, edx, edi, name, &miss);
17677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
17687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register receiver = eax;
17697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register index = edi;
17703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = edx;
17717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = eax;
17727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize));
17737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (argc > 0) {
17747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ mov(index, Operand(esp, (argc - 0) * kPointerSize));
17757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  } else {
177644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ Set(index, Immediate(factory()->undefined_value()));
17777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
17787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
17793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringCharAtGenerator generator(receiver,
17803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  index,
17813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  scratch,
17823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  result,
17833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  &miss,  // When not a string.
17843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  &miss,  // When not a number.
17853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  index_out_of_range_label,
17863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  STRING_INDEX_IS_NUMBER);
17873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateFast(masm());
17887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ ret((argc + 1) * kPointerSize);
17897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StubRuntimeCallHelper call_helper;
17913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateSlow(masm(), call_helper);
17927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1793b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (index_out_of_range.is_linked()) {
1794b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ bind(&index_out_of_range);
179544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ Set(eax, Immediate(factory()->empty_string()));
1796b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ ret((argc + 1) * kPointerSize);
1797b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
17987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
17997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&miss);
1800b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Restore function name in ecx.
18013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Set(ecx, Immediate(name));
1802b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ bind(&name_miss);
18033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
18046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return the generated code.
180625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  return GetCode(function);
18076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
18086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18103ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
18113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
18123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
18133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
18143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
18153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
181659151504615d929945dc59db37bf1166937748c6Steve Block  // ----------- S t a t e -------------
181759151504615d929945dc59db37bf1166937748c6Steve Block  //  -- ecx                 : function name
181859151504615d929945dc59db37bf1166937748c6Steve Block  //  -- esp[0]              : return address
181959151504615d929945dc59db37bf1166937748c6Steve Block  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
182059151504615d929945dc59db37bf1166937748c6Steve Block  //  -- ...
182159151504615d929945dc59db37bf1166937748c6Steve Block  //  -- esp[(argc + 1) * 4] : receiver
182259151504615d929945dc59db37bf1166937748c6Steve Block  // -----------------------------------
182359151504615d929945dc59db37bf1166937748c6Steve Block
182459151504615d929945dc59db37bf1166937748c6Steve Block  const int argc = arguments().immediate();
182559151504615d929945dc59db37bf1166937748c6Steve Block
182659151504615d929945dc59db37bf1166937748c6Steve Block  // If the object is not a JSObject or we got an unexpected number of
182759151504615d929945dc59db37bf1166937748c6Steve Block  // arguments, bail out to the regular call.
182844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!object->IsJSObject() || argc != 1) {
18293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Handle<Code>::null();
183044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
183159151504615d929945dc59db37bf1166937748c6Steve Block
183259151504615d929945dc59db37bf1166937748c6Steve Block  Label miss;
183359151504615d929945dc59db37bf1166937748c6Steve Block  GenerateNameCheck(name, &miss);
183459151504615d929945dc59db37bf1166937748c6Steve Block
18353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (cell.is_null()) {
183659151504615d929945dc59db37bf1166937748c6Steve Block    __ mov(edx, Operand(esp, 2 * kPointerSize));
183759151504615d929945dc59db37bf1166937748c6Steve Block    STATIC_ASSERT(kSmiTag == 0);
18383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(edx, &miss);
18393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
18403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    name, &miss);
184159151504615d929945dc59db37bf1166937748c6Steve Block  } else {
18423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(cell->value() == *function);
18433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
18443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                &miss);
184559151504615d929945dc59db37bf1166937748c6Steve Block    GenerateLoadFunctionFromCell(cell, function, &miss);
184659151504615d929945dc59db37bf1166937748c6Steve Block  }
184759151504615d929945dc59db37bf1166937748c6Steve Block
184859151504615d929945dc59db37bf1166937748c6Steve Block  // Load the char code argument.
184959151504615d929945dc59db37bf1166937748c6Steve Block  Register code = ebx;
185059151504615d929945dc59db37bf1166937748c6Steve Block  __ mov(code, Operand(esp, 1 * kPointerSize));
185159151504615d929945dc59db37bf1166937748c6Steve Block
185259151504615d929945dc59db37bf1166937748c6Steve Block  // Check the code is a smi.
185359151504615d929945dc59db37bf1166937748c6Steve Block  Label slow;
185459151504615d929945dc59db37bf1166937748c6Steve Block  STATIC_ASSERT(kSmiTag == 0);
18553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(code, &slow);
185659151504615d929945dc59db37bf1166937748c6Steve Block
185759151504615d929945dc59db37bf1166937748c6Steve Block  // Convert the smi code to uint16.
185859151504615d929945dc59db37bf1166937748c6Steve Block  __ and_(code, Immediate(Smi::FromInt(0xffff)));
185959151504615d929945dc59db37bf1166937748c6Steve Block
18603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringCharFromCodeGenerator generator(code, eax);
18613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateFast(masm());
186259151504615d929945dc59db37bf1166937748c6Steve Block  __ ret(2 * kPointerSize);
186359151504615d929945dc59db37bf1166937748c6Steve Block
1864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StubRuntimeCallHelper call_helper;
18653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.GenerateSlow(masm(), call_helper);
186659151504615d929945dc59db37bf1166937748c6Steve Block
186759151504615d929945dc59db37bf1166937748c6Steve Block  // Tail call the full function. We do not have to patch the receiver
186859151504615d929945dc59db37bf1166937748c6Steve Block  // because the function makes no use of it.
186959151504615d929945dc59db37bf1166937748c6Steve Block  __ bind(&slow);
18703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
1871257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
1872257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
1873257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
1874257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), call_kind);
187559151504615d929945dc59db37bf1166937748c6Steve Block
187659151504615d929945dc59db37bf1166937748c6Steve Block  __ bind(&miss);
187759151504615d929945dc59db37bf1166937748c6Steve Block  // ecx: function name.
18783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
187959151504615d929945dc59db37bf1166937748c6Steve Block
188059151504615d929945dc59db37bf1166937748c6Steve Block  // Return the generated code.
18813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
188259151504615d929945dc59db37bf1166937748c6Steve Block}
188359151504615d929945dc59db37bf1166937748c6Steve Block
188459151504615d929945dc59db37bf1166937748c6Steve Block
18853ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathFloorCall(
18863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
18873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
18883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
18893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
18903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
18910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // ----------- S t a t e -------------
18920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  //  -- ecx                 : name
18930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  //  -- esp[0]              : return address
18940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
18950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  //  -- ...
18960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  //  -- esp[(argc + 1) * 4] : receiver
18970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // -----------------------------------
18980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
18998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (!CpuFeatures::IsSupported(SSE2)) {
19003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Handle<Code>::null();
190144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
190244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
19030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  CpuFeatures::Scope use_sse2(SSE2);
19040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  const int argc = arguments().immediate();
19060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // If the object is not a JSObject or we got an unexpected number of
19080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // arguments, bail out to the regular call.
190944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!object->IsJSObject() || argc != 1) {
19103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Handle<Code>::null();
191144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
19120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label miss;
19140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  GenerateNameCheck(name, &miss);
19150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (cell.is_null()) {
19170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    __ mov(edx, Operand(esp, 2 * kPointerSize));
19180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    STATIC_ASSERT(kSmiTag == 0);
19203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(edx, &miss);
19210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
19233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    name, &miss);
19240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
19253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(cell->value() == *function);
19263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
19273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                &miss);
19280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    GenerateLoadFunctionFromCell(cell, function, &miss);
19290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
19300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Load the (only) argument into eax.
19320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ mov(eax, Operand(esp, 1 * kPointerSize));
19330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Check if the argument is a smi.
19350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label smi;
19360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  STATIC_ASSERT(kSmiTag == 0);
19373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(eax, &smi);
19380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Check if the argument is a heap number and load its value into xmm0.
19400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label slow;
1941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ CheckMap(eax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK);
19420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ movdbl(xmm0, FieldOperand(eax, HeapNumber::kValueOffset));
19430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Check if the argument is strictly positive. Note this also
19450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // discards NaN.
19460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ xorpd(xmm1, xmm1);
19470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ ucomisd(xmm0, xmm1);
19480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ j(below_equal, &slow);
19490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Do a truncating conversion.
19510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ cvttsd2si(eax, Operand(xmm0));
19520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Check if the result fits into a smi. Note this also checks for
19540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // 0x80000000 which signals a failed conversion.
19550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label wont_fit_into_smi;
19560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ test(eax, Immediate(0xc0000000));
19570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ j(not_zero, &wont_fit_into_smi);
19580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Smi tag and return.
19600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ SmiTag(eax);
19610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&smi);
19620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ ret(2 * kPointerSize);
19630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Check if the argument is < 2^kMantissaBits.
19650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label already_round;
19660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&wont_fit_into_smi);
19670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadPowerOf2(xmm1, ebx, HeapNumber::kMantissaBits);
19680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ ucomisd(xmm0, xmm1);
19690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ j(above_equal, &already_round);
19700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Save a copy of the argument.
19720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ movaps(xmm2, xmm0);
19730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Compute (argument + 2^kMantissaBits) - 2^kMantissaBits.
19750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ addsd(xmm0, xmm1);
19760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ subsd(xmm0, xmm1);
19770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Compare the argument and the tentative result to get the right mask:
19790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  //   if xmm2 < xmm0:
19800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  //     xmm2 = 1...1
19810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  //   else:
19820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  //     xmm2 = 0...0
19830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ cmpltsd(xmm2, xmm0);
19840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Subtract 1 if the argument was less than the tentative result.
19860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ LoadPowerOf2(xmm1, ebx, 0);
19870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ andpd(xmm1, xmm2);
19880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ subsd(xmm0, xmm1);
19890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Return a new heap number.
19910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ AllocateHeapNumber(eax, ebx, edx, &slow);
19920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
19930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ ret(2 * kPointerSize);
19940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
19950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Return the argument (when it's an already round heap number).
19960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&already_round);
19970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ mov(eax, Operand(esp, 1 * kPointerSize));
19980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ ret(2 * kPointerSize);
19990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
20000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Tail call the full function. We do not have to patch the receiver
20010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // because the function makes no use of it.
20020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&slow);
2003257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
2004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), CALL_AS_METHOD);
20050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
20060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&miss);
20070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // ecx: function name.
20083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
20090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
20100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Return the generated code.
20113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
20120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
20130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
20140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
20153ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathAbsCall(
20163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
20173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
20183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
20193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
20203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2021f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // ----------- S t a t e -------------
2022f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- ecx                 : name
2023f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- esp[0]              : return address
2024f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
2025f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- ...
2026f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  //  -- esp[(argc + 1) * 4] : receiver
2027f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // -----------------------------------
2028f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2029f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const int argc = arguments().immediate();
2030f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2031f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // If the object is not a JSObject or we got an unexpected number of
2032f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // arguments, bail out to the regular call.
203344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!object->IsJSObject() || argc != 1) {
20343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Handle<Code>::null();
203544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
2036f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2037f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Label miss;
2038f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  GenerateNameCheck(name, &miss);
2039f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
20403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (cell.is_null()) {
2041f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    __ mov(edx, Operand(esp, 2 * kPointerSize));
2042f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2043f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    STATIC_ASSERT(kSmiTag == 0);
20443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(edx, &miss);
2045f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
20463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
20473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    name, &miss);
2048f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  } else {
20493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(cell->value() == *function);
20503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
20513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                &miss);
2052f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    GenerateLoadFunctionFromCell(cell, function, &miss);
2053f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
2054f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2055f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Load the (only) argument into eax.
2056f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ mov(eax, Operand(esp, 1 * kPointerSize));
2057f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2058f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Check if the argument is a smi.
2059f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Label not_smi;
2060f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
20613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(eax, &not_smi);
2062f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2063f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0
2064f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // otherwise.
2065f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ mov(ebx, eax);
2066f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ sar(ebx, kBitsPerInt - 1);
2067f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2068f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Do bitwise not or do nothing depending on ebx.
20693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ xor_(eax, ebx);
2070f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2071f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Add 1 or do nothing depending on ebx.
20723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sub(eax, ebx);
2073f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2074f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // If the result is still negative, go to the slow case.
2075f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // This only happens for the most negative smi.
2076f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Label slow;
2077f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ j(negative, &slow);
2078f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2079f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Smi case done.
2080f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ ret(2 * kPointerSize);
2081f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2082f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Check if the argument is a heap number and load its exponent and
2083f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // sign into ebx.
2084f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ bind(&not_smi);
2085257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ CheckMap(eax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK);
2086f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ mov(ebx, FieldOperand(eax, HeapNumber::kExponentOffset));
2087f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2088f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Check the sign of the argument. If the argument is positive,
2089f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // just return it.
2090f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Label negative_sign;
2091f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ test(ebx, Immediate(HeapNumber::kSignMask));
2092f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ j(not_zero, &negative_sign);
2093f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ ret(2 * kPointerSize);
2094f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2095f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // If the argument is negative, clear the sign, and return a new
2096f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // number.
2097f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ bind(&negative_sign);
2098f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ and_(ebx, ~HeapNumber::kSignMask);
2099f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ mov(ecx, FieldOperand(eax, HeapNumber::kMantissaOffset));
2100f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ AllocateHeapNumber(eax, edi, edx, &slow);
2101f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ebx);
2102f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx);
2103f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ ret(2 * kPointerSize);
2104f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2105f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Tail call the full function. We do not have to patch the receiver
2106f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // because the function makes no use of it.
2107f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ bind(&slow);
2108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
2109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), CALL_AS_METHOD);
2110f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2111f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ bind(&miss);
2112f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // ecx: function name.
21133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2114f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2115f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Return the generated code.
21163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
2117f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
2118f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2119f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
21203ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileFastApiCall(
212144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    const CallOptimization& optimization,
21223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Object> object,
21233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
21243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
21253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
21263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
212744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(optimization.is_simple_api_call());
212844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Bail out if object is a global object as we don't want to
212944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // repatch it to global receiver.
21303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (object->IsGlobalObject()) return Handle<Code>::null();
21313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!cell.is_null()) return Handle<Code>::null();
21323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsJSObject()) return Handle<Code>::null();
213344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int depth = optimization.GetPrototypeDepthOfExpectedType(
21343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<JSObject>::cast(object), holder);
21353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (depth == kInvalidProtoDepth) return Handle<Code>::null();
213644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
213744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label miss, miss_before_stack_reserved;
213844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
213944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenerateNameCheck(name, &miss_before_stack_reserved);
214044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
214144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Get the receiver from the stack.
214244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const int argc = arguments().immediate();
214344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
214444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
214544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the receiver isn't a smi.
21463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(edx, &miss_before_stack_reserved);
214744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
214844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
214944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_const(), 1);
215044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_const_fast_api(), 1);
215144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
215244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Allocate space for v8::Arguments implicit values. Must be initialized
215344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // before calling any runtime function.
21543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sub(esp, Immediate(kFastApiCallArguments * kPointerSize));
215544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
215644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check that the maps haven't changed and find a Holder as a side effect.
21573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
21583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  name, depth, &miss);
215944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
216044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Move the return address on top of the stack.
216144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(eax, Operand(esp, 3 * kPointerSize));
216244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(Operand(esp, 0 * kPointerSize), eax);
216344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
216444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains
216544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // duplicate of return address and will be overwritten.
21663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateFastApiCall(masm(), optimization, argc);
216744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
216844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&miss);
21693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(esp, Immediate(kFastApiCallArguments * kPointerSize));
217044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
217144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ bind(&miss_before_stack_reserved);
21723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
217344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
217444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Return the generated code.
217544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return GetCode(function);
217644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
217744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
217844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
21793ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object,
21803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSObject> holder,
21813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSFunction> function,
21823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<String> name,
21833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   CheckType check) {
2184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2185e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ecx                 : name
2186e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[0]              : return address
2187e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
2188e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ...
2189e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc + 1) * 4] : receiver
2190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
21916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
219244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (HasCustomCallGenerator(function)) {
21933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> code = CompileCustomCall(object, holder,
21943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          Handle<JSGlobalPropertyCell>::null(),
21953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          function, name);
21963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // A null handle means bail out to the regular compiler code below.
21973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!code.is_null()) return code;
21986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
21996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
220044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label miss;
220144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GenerateNameCheck(name, &miss);
22027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver from the stack.
2204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
2205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
2206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
2208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (check != NUMBER_CHECK) {
22093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(edx, &miss);
2210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that it's okay not to patch the on stack receiver
2213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // unless we're doing a receiver map check.
2214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
2215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (check) {
2216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case RECEIVER_MAP_CHECK:
221744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ IncrementCounter(isolate()->counters()->call_const(), 1);
2218402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Check that the maps haven't changed.
22203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax,
22213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      edi, name, &miss);
2222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Patch the receiver on the stack with the global proxy if
2224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // necessary.
2225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (object->IsGlobalObject()) {
2226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
2227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
2228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
2229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
2230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case STRING_CHECK:
22323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
2233e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the object is a string or a symbol.
22347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax);
2235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ j(above_equal, &miss);
2236e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the maps starting from the prototype haven't changed.
22377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        GenerateDirectLoadGlobalFunctionPrototype(
22380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            masm(), Context::STRING_FUNCTION_INDEX, eax, &miss);
22393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CheckPrototypes(
22403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Handle<JSObject>(JSObject::cast(object->GetPrototype())),
22413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            eax, holder, ebx, edx, edi, name, &miss);
22423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
224385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        // Calling non-strict non-builtins with a value as the receiver
224485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        // requires boxing.
224585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        __ jmp(&miss);
22463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
22473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
22483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case NUMBER_CHECK:
22503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
2251e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        Label fast;
2252e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the object is a smi or a heap number.
22533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        __ JumpIfSmi(edx, &fast);
2254e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax);
2255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ j(not_equal, &miss);
2256e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ bind(&fast);
2257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the maps starting from the prototype haven't changed.
22587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        GenerateDirectLoadGlobalFunctionPrototype(
22590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss);
22603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CheckPrototypes(
22613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Handle<JSObject>(JSObject::cast(object->GetPrototype())),
22623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            eax, holder, ebx, edx, edi, name, &miss);
22633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
226485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        // Calling non-strict non-builtins with a value as the receiver
226585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        // requires boxing.
226685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        __ jmp(&miss);
22673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
22683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
22693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case BOOLEAN_CHECK:
22713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
2272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        Label fast;
2273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the object is a boolean.
227444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ cmp(edx, factory()->true_value());
2275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ j(equal, &fast);
227644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ cmp(edx, factory()->false_value());
2277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ j(not_equal, &miss);
2278e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ bind(&fast);
2279e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Check that the maps starting from the prototype haven't changed.
22807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        GenerateDirectLoadGlobalFunctionPrototype(
22810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss);
22823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CheckPrototypes(
22833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Handle<JSObject>(JSObject::cast(object->GetPrototype())),
22843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            eax, holder, ebx, edx, edi, name, &miss);
22853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
22863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Calling non-strict non-builtins with a value as the receiver
22873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // requires boxing.
22883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ jmp(&miss);
2289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
2290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
2291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
2295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
2296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
2297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), call_kind);
2298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
2300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
23013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
230425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  return GetCode(function);
2305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23083ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
23093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> holder,
23103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<String> name) {
2311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ecx                 : name
2313e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[0]              : return address
2314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
2315e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ...
2316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc + 1) * 4] : receiver
2317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateNameCheck(name, &miss);
23217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the number of arguments.
2323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
2324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LookupResult lookup(isolate());
2326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LookupPostInterceptor(holder, name, &lookup);
2327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver from the stack.
2329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
2330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallInterceptorCompiler compiler(this, arguments(), ecx, extra_state_);
23323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  compiler.Compile(masm(), object, holder, name, &lookup, edx, ebx, edi, eax,
23333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   &miss);
2334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Restore receiver.
2336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
2337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the function really is a function.
23393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(eax, &miss);
2340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
2341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
2342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the receiver on the stack with the global proxy if
2344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // necessary.
2345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsGlobalObject()) {
2346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
2347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
2348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the function.
2351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(edi, eax);
23523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2353257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
2354257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
2355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
2356257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), call_kind);
2357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle load cache miss.
2359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
23603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23673ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallGlobal(
23683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
23693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<GlobalObject> holder,
23703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
23713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function,
23723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ecx                 : name
2375e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[0]              : return address
2376e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
2377e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ...
2378e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc + 1) * 4] : receiver
2379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
238059151504615d929945dc59db37bf1166937748c6Steve Block
238144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (HasCustomCallGenerator(function)) {
23823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> code = CompileCustomCall(object, holder, cell, function, name);
23833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // A null handle means bail out to the regular compiler code below.
23843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!code.is_null()) return code;
238559151504615d929945dc59db37bf1166937748c6Steve Block  }
238659151504615d929945dc59db37bf1166937748c6Steve Block
2387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
23887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateNameCheck(name, &miss);
23897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the number of arguments.
2391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = arguments().immediate();
239259151504615d929945dc59db37bf1166937748c6Steve Block  GenerateGlobalReceiverCheck(object, holder, name, &miss);
239359151504615d929945dc59db37bf1166937748c6Steve Block  GenerateLoadFunctionFromCell(cell, function, &miss);
2394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the receiver on the stack with the global proxy.
2396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsGlobalObject()) {
2397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
2398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
2399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the context (function already in edi).
2402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
2403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the cached code (tail call).
240544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
240644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_global_inline(), 1);
2407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount expected(function->shared()->formal_parameter_count());
24083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
2410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
24113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We call indirectly through the code field in the function to
24123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // allow recompilation to take effect without changing any of the
24133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // call sites.
24143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
24153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                expected, arguments(), JUMP_FUNCTION,
24163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                NullCallWrapper(), call_kind);
2417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle call cache miss.
2419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
242044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->call_global_inline_miss(), 1);
24213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMissBranch();
2422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(NORMAL, name);
2425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24283ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
24295913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                  int index,
24303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                  Handle<Map> transition,
24313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                  Handle<String> name) {
2432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- eax    : value
2434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
24354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- edx    : receiver
2436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Generate store field code.  Trashes the name register.
24413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateStoreField(masm(), object, index, transition, edx, ecx, ebx, &miss);
2442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
24453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(ecx, Immediate(name));  // restore name
244644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(ic, RelocInfo::CODE_TARGET);
2448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
24503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name);
2451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24543ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreCallback(
24553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
24563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<AccessorInfo> callback,
24573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- eax    : value
2460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
24614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- edx    : receiver
2462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the object hasn't changed.
24673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(edx, Handle<Map>(object->map()),
24683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              &miss, DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
2469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform global security token check if needed.
2471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object->IsJSGlobalProxy()) {
24724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ CheckAccessGlobalProxy(edx, ebx, &miss);
2473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub never generated for non-global objects that require access
2476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // checks.
2477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
2478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(ebx);  // remove the return address
24804515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ push(edx);  // receiver
24813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(Immediate(callback));  // callback info
2482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ecx);  // name
2483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(eax);  // value
2484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ebx);  // restore return address
2485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do tail-call to the runtime system.
2487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference store_callback_property =
248844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
24896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallExternalReference(store_callback_property, 4, 1);
2490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
249344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(ic, RelocInfo::CODE_TARGET);
2495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25013ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreInterceptor(
25023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
25033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- eax    : value
2506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
25074515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- edx    : receiver
2508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the object hasn't changed.
25133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(edx, Handle<Map>(receiver->map()),
25143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              &miss, DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
2515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform global security token check if needed.
2517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (receiver->IsJSGlobalProxy()) {
25184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    __ CheckAccessGlobalProxy(edx, ebx, &miss);
2519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub never generated for non-global objects that require access
2522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // checks.
2523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
2524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(ebx);  // remove the return address
25264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ push(edx);  // receiver
2527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ecx);  // name
2528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(eax);  // value
2529e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ push(Immediate(Smi::FromInt(strict_mode_)));
2530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ebx);  // restore return address
2531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do tail-call to the runtime system.
2533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference store_ic_property =
253444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate());
2535e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ TailCallExternalReference(store_ic_property, 4, 1);
2536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
253944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(ic, RelocInfo::CODE_TARGET);
2541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25473ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreGlobal(
25483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<GlobalObject> object,
25493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
25503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- eax    : value
2553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
25544515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- edx    : receiver
2555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the map of the global has not changed.
25604515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
2561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         Immediate(Handle<Map>(object->map())));
2562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
2563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Compute the cell operand to use.
25653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(ebx, Immediate(cell));
25663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Operand cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset);
2567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the value in the cell is not the hole. If it is, this
25691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // cell could have been deleted and reintroducing the global needs
25701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // to update the property details in the property dictionary of the
25711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // global object. We bail out to the runtime system to do that.
257244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmp(cell_operand, factory()->the_hole_value());
25731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ j(equal, &miss);
25741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
25751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Store the value in the cell.
25761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ mov(cell_operand, eax);
25773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // No write barrier here, because cells are always rescanned.
25781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the value (register eax).
258044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
258144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_store_global_inline(), 1);
2582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
2583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
258644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_store_global_inline_miss(), 1);
258744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(ic, RelocInfo::CODE_TARGET);
2589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(NORMAL, name);
2592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25953ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
25965913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                       int index,
25973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                       Handle<Map> transition,
25983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                       Handle<String> name) {
2599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- eax    : value
26016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ecx    : key
26026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- edx    : receiver
2603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
260744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
260844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_store_field(), 1);
2609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
26113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(ecx, Immediate(name));
2612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
2613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Generate store field code.  Trashes the name register.
26153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateStoreField(masm(), object, index, transition, edx, ecx, ebx, &miss);
2616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle store cache miss.
2618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
261944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_store_field(), 1);
262044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(ic, RelocInfo::CODE_TARGET);
2622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
26243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name);
2625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26283ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreElement(
26293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Map> receiver_map) {
2630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // ----------- S t a t e -------------
2631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- eax    : value
2632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- ecx    : key
2633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- edx    : receiver
2634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- esp[0] : return address
2635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // -----------------------------------
2636589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ElementsKind elements_kind = receiver_map->elements_kind();
26373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
26383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> stub =
26393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      KeyedStoreElementStub(is_jsarray, elements_kind, grow_mode_).GetCode();
26403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK);
2642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(ic, RelocInfo::CODE_TARGET);
2645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
26473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string());
2648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
2649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
26513ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
26523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MapHandleList* receiver_maps,
26533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CodeHandleList* handler_stubs,
26543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MapHandleList* transitioned_maps) {
2655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
2656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- eax    : value
2657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ecx    : key
2658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- edx    : receiver
2659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- esp[0] : return address
2660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
2661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
26623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(edx, &miss, Label::kNear);
26633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
26643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ebx: receiver->map().
26653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < receiver_maps->length(); ++i) {
26663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(edi, receiver_maps->at(i));
26673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (transitioned_maps->at(i).is_null()) {
26683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(equal, handler_stubs->at(i));
26693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
26703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label next_map;
26713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(not_equal, &next_map, Label::kNear);
26723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(ebx, Immediate(transitioned_maps->at(i)));
26733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET);
26743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&next_map);
26753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&miss);
2678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss();
2679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
2680e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2681e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Return the generated code.
26823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC);
2683e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2684e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2685e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
26863ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name,
26873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> object,
26883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> last) {
26896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
26906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- eax    : receiver
26916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ecx    : name
26926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- esp[0] : return address
26936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
26946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss;
26956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
26966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the receiver isn't a smi.
26973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(eax, &miss);
26986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
26998defd9ff6930b4e24729971a61cf7469daf119beSteve Block  ASSERT(last->IsGlobalObject() || last->HasFastProperties());
27008defd9ff6930b4e24729971a61cf7469daf119beSteve Block
27016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the maps of the full prototype chain. Also check that
27026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // global property cells up to (but not including) the last object
27036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // in the prototype chain are empty.
27043bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss);
27056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // If the last object in the prototype chain is a global object,
27076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // check that the global property cell is empty.
27086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (last->IsGlobalObject()) {
27093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateCheckPropertyCell(
27103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        masm(), Handle<GlobalObject>::cast(last), name, edx, &miss);
27116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
27126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return undefined if maps of the full prototype chain are still the
27146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // same and no global property with this name contains a value.
271544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(eax, isolate()->factory()->undefined_value());
27166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ret(0);
27176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss);
27196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
27206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Return the generated code.
27223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NONEXISTENT, factory()->empty_string());
27236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
27246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27263ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object,
27273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<JSObject> holder,
27285913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                int index,
27293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Handle<String> name) {
2730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2731402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : receiver
2732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
2733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  GenerateLoadField(object, holder, eax, ebx, edx, edi, index, name, &miss);
2738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(FIELD, name);
2743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27463ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadCallback(
27473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
27483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
27493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
27503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<AccessorInfo> callback) {
2751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2752402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : receiver
2753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
2754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadCallback(object, holder, eax, ecx, ebx, edx, edi, callback,
27593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       name, &miss);
2760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27683ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object,
27693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSObject> holder,
27703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<JSFunction> value,
27713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   Handle<String> name) {
2772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2773402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : receiver
2774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
2775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  GenerateLoadConstant(object, holder, eax, ebx, edx, edi, value, name, &miss);
2780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CONSTANT_FUNCTION, name);
2785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27883ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> receiver,
27893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<JSObject> holder,
27903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                      Handle<String> name) {
2791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2792402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : receiver
2793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
2794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LookupResult lookup(isolate());
2799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LookupPostInterceptor(holder, name, &lookup);
2800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // TODO(368): Compile in the whole chain: all the interceptors in
2802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // prototypes and ultimate answer.
28033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadInterceptor(receiver, holder, &lookup, eax, ecx, edx, ebx, edi,
28043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          name, &miss);
2805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
2807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28143ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadGlobal(
28153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> object,
28163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<GlobalObject> holder,
28173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSGlobalPropertyCell> cell,
28183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
28193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool is_dont_delete) {
2820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2821402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : receiver
2822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
2823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the maps haven't changed.
28283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(eax, &miss);
28293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CheckPrototypes(object, eax, holder, ebx, edx, edi, name, &miss);
2830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the value from the cell.
2832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (Serializer::enabled()) {
28333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(ebx, Immediate(cell));
2834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset));
2835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
28363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(ebx, Operand::Cell(cell));
2837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for deleted property if property can actually be deleted.
2840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!is_dont_delete) {
284144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmp(ebx, factory()->the_hole_value());
2842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(equal, &miss);
2843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (FLAG_debug_code) {
284444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmp(ebx, factory()->the_hole_value());
2845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Check(not_equal, "DontDelete cells can't contain the hole");
2846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
284844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
284944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_load_global_stub(), 1);
2850402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(eax, ebx);
2851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
2852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
285444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->named_load_global_stub_miss(), 1);
2855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::LOAD_IC);
2856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(NORMAL, name);
2859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28623ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name,
28633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     Handle<JSObject> receiver,
28643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                     Handle<JSObject> holder,
28655913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                     int index) {
2866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2867402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
2868402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
2869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
287344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
287444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_field(), 1);
2875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
28773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(eax, Immediate(name));
2878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
2879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28803bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss);
2881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
288344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_field(), 1);
2884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(FIELD, name);
2888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28913ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadCallback(
28923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
28933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
28943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
28953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<AccessorInfo> callback) {
2896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2897402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
2898402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
2899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
290344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
290444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_callback(), 1);
2905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
29073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(eax, Immediate(name));
2908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
2909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadCallback(receiver, holder, edx, eax, ebx, ecx, edi, callback,
29113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       name, &miss);
2912e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
291444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_callback(), 1);
2915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
2919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29223ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadConstant(
29233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name,
29243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
29253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
29263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> value) {
2927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2928402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
2929402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
2930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
293444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
293544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_constant_function(), 1);
2936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
29383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(eax, Immediate(name));
2939257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
2940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadConstant(
29423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      receiver, holder, edx, ebx, ecx, edi, value, name, &miss);
2943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
294444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_constant_function(), 1);
2945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CONSTANT_FUNCTION, name);
2949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29523ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor(
29533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> receiver,
29543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSObject> holder,
29553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2957402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
2958402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
2959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
296344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
296444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_interceptor(), 1);
2965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
29673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(eax, Immediate(name));
2968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
2969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LookupResult lookup(isolate());
2971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LookupPostInterceptor(holder, name, &lookup);
29723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadInterceptor(receiver, holder, &lookup, edx, eax, ecx, ebx, edi,
29733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          name, &miss);
2974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
297544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_interceptor(), 1);
2976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
2979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(INTERCEPTOR, name);
2980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29833ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength(
29843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
2985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2986402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
2987402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
2988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
2989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
2991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
299244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
299344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_array_length(), 1);
2994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
29963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(eax, Immediate(name));
2997257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
2998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2999402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateLoadArrayLength(masm(), edx, ecx, &miss);
3000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
300144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_array_length(), 1);
3002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
3005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
3006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30093ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadStringLength(
30103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
3011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
3012402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
3013402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
3014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
3015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
3016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
3017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
301844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
301944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_string_length(), 1);
3020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
30223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(eax, Immediate(name));
3023257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
3024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true);
3026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
302744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_string_length(), 1);
3028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
3031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
3032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30353ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype(
30363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name) {
3037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
3038402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
3039402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
3040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
3041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
3042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
3043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
304444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
304544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_function_prototype(), 1);
3046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the name has not changed.
30483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(eax, Immediate(name));
3049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
3050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3051402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss);
3052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
305344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ DecrementCounter(counters->keyed_load_function_prototype(), 1);
3054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
3057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode(CALLBACKS, name);
3058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30613ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadElement(
30623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Map> receiver_map) {
3063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // ----------- S t a t e -------------
3064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- eax    : key
3065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- edx    : receiver
3066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- esp[0] : return address
3067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // -----------------------------------
30683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3069589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ElementsKind elements_kind = receiver_map->elements_kind();
30703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode();
30713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK);
3073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Return the generated code.
30773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string());
3078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
30813ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic(
30823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MapHandleList* receiver_maps,
30833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CodeHandleList* handler_ics) {
3084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3085257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- eax    : key
3086257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- edx    : receiver
3087257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- esp[0] : return address
3088257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3089257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
3090257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfSmi(edx, &miss);
3091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register map_reg = ebx;
3093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(map_reg, FieldOperand(edx, HeapObject::kMapOffset));
3094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int receiver_count = receiver_maps->length();
3095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int current = 0; current < receiver_count; ++current) {
30963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(map_reg, receiver_maps->at(current));
30973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(equal, handler_ics->at(current));
3098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&miss);
3101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Return the generated code.
31043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC);
3105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Specialized stub for constructing objects from functions which only have only
3109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// simple assignments of the form this.x = ...; in their body.
31103ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> ConstructStubCompiler::CompileConstructStub(
31113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<JSFunction> function) {
3112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
3113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- eax : argc
3114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- edi : constructor
3115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
3116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[4] : last argument
3117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
3118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label generic_stub_call;
3119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
3120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check to see whether there are any break points in the function code. If
3121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // there are jump to the generic constructor stub which calls the actual
3122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // code for the function thereby hitting the break points.
3123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
3124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kDebugInfoOffset));
312544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ cmp(ebx, factory()->undefined_value());
3126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &generic_stub_call);
3127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
3128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the initial map and verify that it is in fact a map.
3130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
3131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Will both indicate a NULL and a Smi.
31323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(ebx, &generic_stub_call);
3133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpObjectType(ebx, MAP_TYPE, ecx);
3134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &generic_stub_call);
3135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
3137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Cannot construct functions this way.
3138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // edi: constructor
3139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ebx: initial map
3140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpInstanceType(ebx, JS_FUNCTION_TYPE);
3141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Assert(not_equal, "Function constructed by construct stub.");
3142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
3143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Now allocate the JSObject on the heap by moving the new space allocation
3145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // top forward.
3146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // edi: constructor
3147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ebx: initial map
3148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset));
3149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ shl(ecx, kPointerSizeLog2);
31503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ AllocateInNewSpace(ecx, edx, ecx, no_reg,
31513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        &generic_stub_call, NO_ALLOCATION_FLAGS);
3152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocated the JSObject, now initialize the fields and add the heap tag.
3154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ebx: initial map
3155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // edx: JSObject (untagged)
3156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(Operand(edx, JSObject::kMapOffset), ebx);
315744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(ebx, factory()->empty_fixed_array());
3158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(Operand(edx, JSObject::kPropertiesOffset), ebx);
3159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(Operand(edx, JSObject::kElementsOffset), ebx);
3160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Push the allocated object to the stack. This is the object that will be
3162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // returned (after it is tagged).
3163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(edx);
3164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // eax: argc
3166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // edx: JSObject (untagged)
3167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the address of the first in-object property into edx.
3168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ lea(edx, Operand(edx, JSObject::kHeaderSize));
3169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate the location of the first argument. The stack contains the
3170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // allocated object and the return address on top of the argc arguments.
3171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ lea(ecx, Operand(esp, eax, times_4, 1 * kPointerSize));
3172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use edi for holding undefined which is used in several places below.
317444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(edi, factory()->undefined_value());
3175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // eax: argc
3177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ecx: first argument
3178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // edx: first in-object property of the JSObject
3179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // edi: undefined
3180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill the initialized properties with a constant value or a passed argument
3181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // depending on the this.x = ...; assignment in the function.
31823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<SharedFunctionInfo> shared(function->shared());
3183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < shared->this_property_assignments_count(); i++) {
3184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (shared->IsThisPropertyAssignmentArgument(i)) {
3185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Check if the argument assigned to the property is actually passed.
3186e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // If argument is not passed the property is set to undefined,
3187e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // otherwise find it on the stack.
3188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int arg_number = shared->GetThisPropertyAssignmentArgument(i);
3189e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ mov(ebx, edi);
3190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ cmp(eax, arg_number);
31918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (CpuFeatures::IsSupported(CMOV)) {
3192e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        CpuFeatures::Scope use_cmov(CMOV);
3193e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ cmov(above, ebx, Operand(ecx, arg_number * -kPointerSize));
3194e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      } else {
3195e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        Label not_passed;
3196e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ j(below_equal, &not_passed);
3197e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ mov(ebx, Operand(ecx, arg_number * -kPointerSize));
3198e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        __ bind(&not_passed);
3199e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
3200e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Store value in the property.
3201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ mov(Operand(edx, i * kPointerSize), ebx);
3202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
3203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Set the property to the constant value.
3204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i));
3205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ mov(Operand(edx, i * kPointerSize), Immediate(constant));
3206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
3207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill the unused in-object property fields with undefined.
32108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ASSERT(function->has_initial_map());
3211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = shared->this_property_assignments_count();
32128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang       i < function->initial_map()->inobject_properties();
3213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       i++) {
3214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(Operand(edx, i * kPointerSize), edi);
3215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move argc to ebx and retrieve and tag the JSObject to return.
3218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(ebx, eax);
3219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(eax);
32203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ or_(eax, Immediate(kHeapObjectTag));
3221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Remove caller arguments and receiver from the stack and return.
3223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(ecx);
3224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ lea(esp, Operand(esp, ebx, times_pointer_size, 1 * kPointerSize));
3225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ecx);
322644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate()->counters();
322744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->constructed_objects(), 1);
322844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->constructed_objects_stub(), 1);
3229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
3230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the generic stub in case the specialized code cannot handle the
3232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // construction.
3233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&generic_stub_call);
32343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> code = isolate()->builtins()->JSConstructStubGeneric();
32353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(code, RelocInfo::CODE_TARGET);
3236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the generated code.
3238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return GetCode();
3239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
32423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#undef __
32433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#define __ ACCESS_MASM(masm)
32443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
32453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
32463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
32473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MacroAssembler* masm) {
32481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ----------- S t a t e -------------
32491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- eax    : key
32501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- edx    : receiver
32511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- esp[0] : return address
32521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
32533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label slow, miss_force_generic;
3254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
32553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
32563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // have been verified by the caller to not be a smi.
32573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(eax, &miss_force_generic);
32583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(ebx, eax);
32593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SmiUntag(ebx);
32603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
32611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
32623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Push receiver on the stack to free up a register for the dictionary
32633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // probing.
32643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ push(edx);
32653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ LoadFromNumberDictionary(&slow,
32663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              ecx,
32673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              eax,
32683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              ebx,
32693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              edx,
32703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              edi,
32713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              eax);
32723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Pop receiver before returning.
32733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ pop(edx);
32743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ret(0);
3275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
32763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&slow);
32773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ pop(edx);
3278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- eax    : value
3281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ecx    : key
3282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- edx    : receiver
3283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- esp[0] : return address
3284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
32863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> slow_ic =
32873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_Slow();
32883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(slow_ic, RelocInfo::CODE_TARGET);
3289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
32903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&miss_force_generic);
32913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ----------- S t a t e -------------
32923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- eax    : value
32933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- ecx    : key
32943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- edx    : receiver
32953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- esp[0] : return address
32963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
3297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
32983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> miss_force_generic_ic =
32993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
33003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(miss_force_generic_ic, RelocInfo::CODE_TARGET);
33013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
3302257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadExternalArray(
3305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    MacroAssembler* masm,
3306589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    ElementsKind elements_kind) {
3307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3308257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- eax    : key
3309257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- edx    : receiver
3310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- esp[0] : return address
3311257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss_force_generic, failed_allocation, slow;
3313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
3315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
33161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the key is a smi.
33183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(eax, &miss_force_generic);
33191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the index is in range.
3321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
332269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ cmp(eax, FieldOperand(ebx, ExternalArray::kLengthOffset));
33231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Unsigned comparison catches both negative and too-large values.
3324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(above_equal, &miss_force_generic);
33251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset));
33261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ebx: base pointer of external storage
33273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  switch (elements_kind) {
3328589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_BYTE_ELEMENTS:
332969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ SmiUntag(eax);  // Untag the index.
333069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ movsx_b(eax, Operand(ebx, eax, times_1, 0));
33311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3332589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3333589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_PIXEL_ELEMENTS:
333469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ SmiUntag(eax);  // Untag the index.
333569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ movzx_b(eax, Operand(ebx, eax, times_1, 0));
33361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3337589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_SHORT_ELEMENTS:
333869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ movsx_w(eax, Operand(ebx, eax, times_1, 0));
33391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3340589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
334169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ movzx_w(eax, Operand(ebx, eax, times_1, 0));
33421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3343589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
3344589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_INT_ELEMENTS:
334569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ mov(ecx, Operand(ebx, eax, times_2, 0));
33461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3347589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_FLOAT_ELEMENTS:
334869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ fld_s(Operand(ebx, eax, times_2, 0));
33491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3350589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_DOUBLE_ELEMENTS:
335169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ fld_d(Operand(ebx, eax, times_4, 0));
3352257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      break;
33531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    default:
33541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      UNREACHABLE();
33551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
33561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
33571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // For integer array types:
33591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ecx: value
33601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // For floating-point array type:
33611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // FP(0): value
33621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3363589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (elements_kind == EXTERNAL_INT_ELEMENTS ||
3364589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) {
33651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // For the Int and UnsignedInt array types, we need to see whether
33661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // the value can be represented in a Smi. If not, we need to convert
33671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // it to a HeapNumber.
33681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Label box_int;
3369589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (elements_kind == EXTERNAL_INT_ELEMENTS) {
33701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ cmp(ecx, 0xC0000000);
33711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ j(sign, &box_int);
33721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    } else {
3373589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind);
33741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // The test is different for unsigned int values. Since we need
33751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // the value to be in the range of a positive smi, we can't
33761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // handle either of the top two bits being set in the value.
33771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ test(ecx, Immediate(0xC0000000));
33781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ j(not_zero, &box_int);
33791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
33801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ mov(eax, ecx);
33821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ SmiTag(eax);
33831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ ret(0);
33841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ bind(&box_int);
33861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Allocate a HeapNumber for the int and perform int-to-double
33881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // conversion.
3389589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (elements_kind == EXTERNAL_INT_ELEMENTS) {
33901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ push(ecx);
33911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ fild_s(Operand(esp, 0));
33921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ pop(ecx);
33931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    } else {
3394589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind);
33951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Need to zero-extend the value.
33961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // There's no fild variant for unsigned values, so zero-extend
33971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // to a 64-bit int manually.
33981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ push(Immediate(0));
33991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ push(ecx);
34001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ fild_d(Operand(esp, 0));
34011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ pop(ecx);
34021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ pop(ecx);
34031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
34041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // FP(0): value
34051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation);
34061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Set the value.
34071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ mov(eax, ecx);
34081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
34091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ ret(0);
3410589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
3411589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch             elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
34121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // For the floating-point array type, we need to always allocate a
34131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // HeapNumber.
34141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation);
34151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Set the value.
34161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ mov(eax, ecx);
34171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
34181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ ret(0);
34191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
34201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ SmiTag(eax);
34211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ ret(0);
34221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
34231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // If we fail allocation of the HeapNumber, we still have a value on
34251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // top of the FPU stack. Remove it.
34261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&failed_allocation);
34273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ fstp(0);
34281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Fall through to slow case.
34291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Slow case: Jump to runtime.
34311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&slow);
3432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Counters* counters = masm->isolate()->counters();
343344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_external_array_slow(), 1);
3434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
34351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ----------- S t a t e -------------
34361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- eax    : key
34371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- edx    : receiver
34381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- esp[0] : return address
34391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
34401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Slow();
3442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(ic, RelocInfo::CODE_TARGET);
34431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- eax    : key
3446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- edx    : receiver
3447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- esp[0] : return address
3448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
34491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Miss case: Jump to runtime.
3451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
3452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> miss_ic =
3453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
34551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
34561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreExternalArray(
3459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    MacroAssembler* masm,
3460589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    ElementsKind elements_kind) {
34611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ----------- S t a t e -------------
3462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- eax    : key
34631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- edx    : receiver
34641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- esp[0] : return address
34651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
3466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss_force_generic, slow, check_heap_number;
346744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
3469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
347044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
34711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the key is a smi.
34723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(ecx, &miss_force_generic);
34731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Check that the index is in range.
347544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
347669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ cmp(ecx, FieldOperand(edi, ExternalArray::kLengthOffset));
34771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Unsigned comparison catches both negative and too-large values.
34781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ j(above_equal, &slow);
34791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
34801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Handle both smis and HeapNumbers in the fast path. Go to the
34811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // runtime for all other kinds of values.
34821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // eax: value
34831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // edx: receiver
34841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ecx: key
34851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // edi: elements array
3486589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) {
34873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfNotSmi(eax, &slow);
34883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
34893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfNotSmi(eax, &check_heap_number);
34903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
349144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
34921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // smi case
349369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ mov(ebx, eax);  // Preserve the value in eax as the return value.
349469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ SmiUntag(ebx);
34951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
349669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // edi: base pointer of external storage
34973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  switch (elements_kind) {
3498589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_PIXEL_ELEMENTS:
349969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ ClampUint8(ebx);
350069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ SmiUntag(ecx);
350169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ mov_b(Operand(edi, ecx, times_1, 0), ebx);
350244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      break;
3503589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_BYTE_ELEMENTS:
3504589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
350569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ SmiUntag(ecx);
350669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ mov_b(Operand(edi, ecx, times_1, 0), ebx);
35071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3508589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_SHORT_ELEMENTS:
3509589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
351069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ mov_w(Operand(edi, ecx, times_1, 0), ebx);
35111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3512589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_INT_ELEMENTS:
3513589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
351469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ mov(Operand(edi, ecx, times_2, 0), ebx);
35151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
3516589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_FLOAT_ELEMENTS:
3517589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    case EXTERNAL_DOUBLE_ELEMENTS:
35181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Need to perform int-to-float conversion.
351969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ push(ebx);
35201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ fild_s(Operand(esp, 0));
352169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ pop(ebx);
3522589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
352369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ fstp_s(Operand(edi, ecx, times_2, 0));
3524589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      } else {  // elements_kind == EXTERNAL_DOUBLE_ELEMENTS.
352569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        __ fstp_d(Operand(edi, ecx, times_4, 0));
3526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
35271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
35281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    default:
35291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      UNREACHABLE();
35301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      break;
35311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
35321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ ret(0);  // Return the original value.
35331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
353444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // TODO(danno): handle heap number -> pixel array conversion
3535589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) {
353644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ bind(&check_heap_number);
353744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // eax: value
353844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // edx: receiver
353944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // ecx: key
354044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // edi: elements array
354144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
3542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch           Immediate(masm->isolate()->factory()->heap_number_map()));
354344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ j(not_equal, &slow);
354444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
354544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // The WebGL specification leaves the behavior of storing NaN and
354644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // +/-Infinity into integer arrays basically undefined. For more
354744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // reproducible behavior, convert these to zero.
354844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
354944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // edi: base pointer of external storage
3550589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
355144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
355269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ fstp_s(Operand(edi, ecx, times_2, 0));
355344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ ret(0);
3554589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
3555257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
355669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      __ fstp_d(Operand(edi, ecx, times_4, 0));
3557257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ ret(0);
355844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else {
355944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // Perform float-to-int conversion with truncation (round-to-zero)
356044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // behavior.
356144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
356244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // For the moment we make the slow call to the runtime on
356344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // processors that don't support SSE2. The code in IntegerConvert
356444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // (code-stubs-ia32.cc) is roughly what is needed here though the
356544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      // conversion failure case does not need to be handled.
35668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (CpuFeatures::IsSupported(SSE2)) {
3567589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        if (elements_kind != EXTERNAL_INT_ELEMENTS &&
3568589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            elements_kind != EXTERNAL_UNSIGNED_INT_ELEMENTS) {
35698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          ASSERT(CpuFeatures::IsSupported(SSE2));
35701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          CpuFeatures::Scope scope(SSE2);
357169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          __ cvttsd2si(ebx, FieldOperand(eax, HeapNumber::kValueOffset));
357244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          // ecx: untagged integer value
35733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          switch (elements_kind) {
3574589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            case EXTERNAL_PIXEL_ELEMENTS:
357569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              __ ClampUint8(ebx);
357669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              // Fall through.
3577589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            case EXTERNAL_BYTE_ELEMENTS:
3578589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
357969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              __ SmiUntag(ecx);
358069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              __ mov_b(Operand(edi, ecx, times_1, 0), ebx);
358144f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
3582589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            case EXTERNAL_SHORT_ELEMENTS:
3583589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
358469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              __ mov_w(Operand(edi, ecx, times_1, 0), ebx);
358544f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
358644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            default:
358744f0eee88ff00398ff7f715fab053374d808c90dSteve Block              UNREACHABLE();
358844f0eee88ff00398ff7f715fab053374d808c90dSteve Block              break;
358944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          }
359044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
35918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          if (CpuFeatures::IsSupported(SSE3)) {
359244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            CpuFeatures::Scope scope(SSE3);
359344f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // fisttp stores values as signed integers. To represent the
359444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // entire range of int and unsigned int arrays, store as a
359544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // 64-bit int and discard the high 32 bits.
359644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // If the value is NaN or +/-infinity, the result is 0x80000000,
359744f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // which is automatically zero when taken mod 2^n, n < 32.
359844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
35993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ sub(esp, Immediate(2 * kPointerSize));
360044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            __ fisttp_d(Operand(esp, 0));
360169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            __ pop(ebx);
36023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ add(esp, Immediate(kPointerSize));
360344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else {
36048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            ASSERT(CpuFeatures::IsSupported(SSE2));
360544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            CpuFeatures::Scope scope(SSE2);
360644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // We can easily implement the correct rounding behavior for the
360744f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // range [0, 2^31-1]. For the time being, to keep this code simple,
360844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // make the slow runtime call for values outside this range.
360944f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // Note: we could do better for signed int arrays.
361044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            __ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset));
361144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            // We will need the key if we have to make the slow runtime call.
361269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            __ push(ebx);
361369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            __ LoadPowerOf2(xmm1, ebx, 31);
361469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            __ pop(ebx);
361544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            __ ucomisd(xmm1, xmm0);
361644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            __ j(above_equal, &slow);
361769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            __ cvttsd2si(ebx, Operand(xmm0));
361844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          }
361969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          // ebx: untagged integer value
362069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          __ mov(Operand(edi, ecx, times_2, 0), ebx);
36211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        }
362244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        __ ret(0);  // Return original value.
36231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
36241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
36251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
36261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Slow case: call runtime.
36281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&slow);
3629257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Counters* counters = masm->isolate()->counters();
3630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->keyed_store_external_array_slow(), 1);
3631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
36321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // ----------- S t a t e -------------
36331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- eax    : value
36341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- ecx    : key
36351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- edx    : receiver
36361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //  -- esp[0] : return address
36371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // -----------------------------------
36381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow();
3640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(ic, RelocInfo::CODE_TARGET);
3641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- eax    : value
3644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ecx    : key
3645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- edx    : receiver
3646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- esp[0] : return address
3647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
3650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> miss_ic =
3651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
3657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
3658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- eax    : key
3659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- edx    : receiver
3660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- esp[0] : return address
3661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
3662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss_force_generic;
3663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
3665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
3666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is a smi.
36683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(eax, &miss_force_generic);
3669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the elements array.
3671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
3672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ AssertFastElements(ecx);
3673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is within bounds.
3675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset));
3676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(above_equal, &miss_force_generic);
3677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the result and make sure it's not the hole.
3679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(ebx, Operand(ecx, eax, times_2,
3680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      FixedArray::kHeaderSize - kHeapObjectTag));
3681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ cmp(ebx, masm->isolate()->factory()->the_hole_value());
3682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(equal, &miss_force_generic);
3683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(eax, ebx);
3684257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ret(0);
3685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
3687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> miss_ic =
3688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
36933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(
36943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MacroAssembler* masm) {
36953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ----------- S t a t e -------------
36963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- eax    : key
36973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- edx    : receiver
36983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- esp[0] : return address
36993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
37003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label miss_force_generic, slow_allocate_heapnumber;
37013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
37033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // have been verified by the caller to not be a smi.
37043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is a smi.
37063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(eax, &miss_force_generic);
37073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Get the elements array.
37093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
37103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ AssertFastElements(ecx);
37113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is within bounds.
37133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmp(eax, FieldOperand(ecx, FixedDoubleArray::kLengthOffset));
37143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(above_equal, &miss_force_generic);
37153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check for the hole
37173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
37183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmp(FieldOperand(ecx, eax, times_4, offset), Immediate(kHoleNanUpper32));
37193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(equal, &miss_force_generic);
37203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Always allocate a heap number for the result.
37223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (CpuFeatures::IsSupported(SSE2)) {
37233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    CpuFeatures::Scope use_sse2(SSE2);
37243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ movdbl(xmm0, FieldOperand(ecx, eax, times_4,
37253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                 FixedDoubleArray::kHeaderSize));
37263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
37273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ fld_d(FieldOperand(ecx, eax, times_4, FixedDoubleArray::kHeaderSize));
37283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
37293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ AllocateHeapNumber(ecx, ebx, edi, &slow_allocate_heapnumber);
37303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Set the value.
37313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (CpuFeatures::IsSupported(SSE2)) {
37323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    CpuFeatures::Scope use_sse2(SSE2);
37333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ movdbl(FieldOperand(ecx, HeapNumber::kValueOffset), xmm0);
37343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
37353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ fstp_d(FieldOperand(ecx, HeapNumber::kValueOffset));
37363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
37373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(eax, ecx);
37383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ret(0);
37393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&slow_allocate_heapnumber);
37413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // A value was pushed on the floating point stack before the allocation, if
37423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // the allocation fails it needs to be removed.
37433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (!CpuFeatures::IsSupported(SSE2)) {
37443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ fstp(0);
37453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
37463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> slow_ic =
37473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_Slow();
37483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(slow_ic, RelocInfo::CODE_TARGET);
37493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&miss_force_generic);
37513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> miss_ic =
37523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
37533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
37543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
37553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastElement(
37583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MacroAssembler* masm,
37593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool is_js_array,
37603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKind elements_kind,
37613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    KeyedAccessGrowMode grow_mode) {
3762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
37633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- eax    : value
37643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- ecx    : key
3765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- edx    : receiver
3766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- esp[0] : return address
3767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
37683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label miss_force_generic, grow, slow, transition_elements_kind;
37693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label check_capacity, prepare_slow, finish_store, commit_backing_store;
3770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
3772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // have been verified by the caller to not be a smi.
3773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the key is a smi.
37753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(ecx, &miss_force_generic);
37761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
37773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
37783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfNotSmi(eax, &transition_elements_kind);
37793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
37803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the elements array and make sure it is a fast element array, not 'cow'.
3782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
3783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (is_js_array) {
3784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check that the key is within bounds.
3785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset));  // smis.
37863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (grow_mode == ALLOW_JSARRAY_GROWTH) {
37873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(above_equal, &grow);
37883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
37893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(above_equal, &miss_force_generic);
37903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
3792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check that the key is within bounds.
3793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset));  // smis.
3794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(above_equal, &miss_force_generic);
3795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
37973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(FieldOperand(edi, HeapObject::kMapOffset),
37983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         Immediate(masm->isolate()->factory()->fixed_array_map()));
37993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_equal, &miss_force_generic);
38003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&finish_store);
38023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
38033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // ecx is a smi, use times_half_pointer_size instead of
38043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // times_pointer_size
38053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(FieldOperand(edi,
38063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        ecx,
38073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        times_half_pointer_size,
38083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        FixedArray::kHeaderSize), eax);
38093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
38103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(elements_kind == FAST_ELEMENTS);
38113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Do the store and update the write barrier.
38123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // ecx is a smi, use times_half_pointer_size instead of
38133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // times_pointer_size
38143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lea(ecx, FieldOperand(edi,
38153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             ecx,
38163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             times_half_pointer_size,
38173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             FixedArray::kHeaderSize));
38183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(Operand(ecx, 0), eax);
38193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure to preserve the value in register eax.
38203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(ebx, eax);
38213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWrite(edi, ecx, ebx, kDontSaveFPRegs);
38223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Done.
3825257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ret(0);
38261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Handle store cache miss, replacing the ic with the generic stub.
3828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss_force_generic);
3829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> ic_force_generic =
3830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
38323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Handle transition to other elements kinds without using the generic stub.
38343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&transition_elements_kind);
38353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
38363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(ic_miss, RelocInfo::CODE_TARGET);
38373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
38393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Handle transition requiring the array to grow.
38403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&grow);
38413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure the array is only growing by a single element, anything else
38433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // must be handled by the runtime. Flags are already set by previous
38443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // compare.
38453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &miss_force_generic);
38463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for the empty array, and preallocate a small backing store if
38483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // possible.
38493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
38503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(edi, Immediate(masm->isolate()->factory()->empty_fixed_array()));
38513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &check_capacity);
38523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int size = FixedArray::SizeFor(JSArray::kPreallocatedArrayElements);
38543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ AllocateInNewSpace(size, edi, ebx, ecx, &prepare_slow, TAG_OBJECT);
38553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Restore the key, which is known to be the array length.
38563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // eax: value
38583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // ecx: key
38593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // edx: receiver
38603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // edi: elements
38613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure that the backing store can hold additional elements.
38623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(FieldOperand(edi, JSObject::kMapOffset),
38633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Immediate(masm->isolate()->factory()->fixed_array_map()));
38643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(FieldOperand(edi, FixedArray::kLengthOffset),
38653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Immediate(Smi::FromInt(JSArray::kPreallocatedArrayElements)));
38663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(ebx, Immediate(masm->isolate()->factory()->the_hole_value()));
38673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = 1; i < JSArray::kPreallocatedArrayElements; ++i) {
38683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(FieldOperand(edi, FixedArray::SizeFor(i)), ebx);
38693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
38703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Store the element at index zero.
38723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(FieldOperand(edi, FixedArray::SizeFor(0)), eax);
38733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Install the new backing store in the JSArray.
38753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(FieldOperand(edx, JSObject::kElementsOffset), edi);
38763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteField(edx, JSObject::kElementsOffset, edi, ebx,
38773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
38783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Increment the length of the array.
38803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(FieldOperand(edx, JSArray::kLengthOffset),
38813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Immediate(Smi::FromInt(1)));
38823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ret(0);
38833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&check_capacity);
38853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(FieldOperand(edi, HeapObject::kMapOffset),
38863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Immediate(masm->isolate()->factory()->fixed_cow_array_map()));
38873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(equal, &miss_force_generic);
38883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // eax: value
38903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // ecx: key
38913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // edx: receiver
38923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // edi: elements
38933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure that the backing store can hold additional elements.
38943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset));
38953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(above_equal, &slow);
38963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Grow the array and finish the store.
38983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(FieldOperand(edx, JSArray::kLengthOffset),
38993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Immediate(Smi::FromInt(1)));
39003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&finish_store);
39013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&prepare_slow);
39033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Restore the key, which is known to be the array length.
39043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(ecx, Immediate(0));
39053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&slow);
39073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
39083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(ic_slow, RelocInfo::CODE_TARGET);
39093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
39101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
39111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
39121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
39133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
39143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MacroAssembler* masm,
39153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool is_js_array,
39163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    KeyedAccessGrowMode grow_mode) {
39173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ----------- S t a t e -------------
39183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- eax    : value
39193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- ecx    : key
39203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- edx    : receiver
39213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- esp[0] : return address
39223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
39233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label miss_force_generic, transition_elements_kind, grow, slow;
39243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label check_capacity, prepare_slow, finish_store, commit_backing_store;
39253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
39263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // This stub is meant to be tail-jumped to, the receiver must already
39273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // have been verified by the caller to not be a smi.
39283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
39293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is a smi.
39303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(ecx, &miss_force_generic);
39313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
39323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Get the elements array.
39333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
39343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ AssertFastElements(edi);
39353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
39363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (is_js_array) {
39373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Check that the key is within bounds.
39383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset));  // smis.
39393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (grow_mode == ALLOW_JSARRAY_GROWTH) {
39403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(above_equal, &grow);
39413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
39423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(above_equal, &miss_force_generic);
39433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
39443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
39453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Check that the key is within bounds.
39463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset));  // smis.
39473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(above_equal, &miss_force_generic);
394885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  }
394985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
39503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&finish_store);
39513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ StoreNumberToDoubleElements(eax, edi, ecx, edx, xmm0,
39523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 &transition_elements_kind, true);
39533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ret(0);
39543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
39553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Handle store cache miss, replacing the ic with the generic stub.
39563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&miss_force_generic);
39573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> ic_force_generic =
39583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
39593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
39603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Handle transition to other elements kinds without using the generic stub.
39623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&transition_elements_kind);
39633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
39643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(ic_miss, RelocInfo::CODE_TARGET);
39653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
39673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Handle transition requiring the array to grow.
39683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&grow);
39693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure the array is only growing by a single element, anything else
39713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // must be handled by the runtime. Flags are already set by previous
39723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // compare.
39733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &miss_force_generic);
39743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Transition on values that can't be stored in a FixedDoubleArray.
39763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label value_is_smi;
39773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfSmi(eax, &value_is_smi);
39783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
39793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Immediate(Handle<Map>(masm->isolate()->heap()->heap_number_map())));
39803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &transition_elements_kind);
39813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&value_is_smi);
39823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for the empty array, and preallocate a small backing store if
39843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // possible.
39853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
39863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(edi, Immediate(masm->isolate()->factory()->empty_fixed_array()));
39873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &check_capacity);
39883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int size = FixedDoubleArray::SizeFor(JSArray::kPreallocatedArrayElements);
39903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ AllocateInNewSpace(size, edi, ebx, ecx, &prepare_slow, TAG_OBJECT);
39913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Restore the key, which is known to be the array length.
39923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(ecx, Immediate(0));
39933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // eax: value
39953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // ecx: key
39963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // edx: receiver
39973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // edi: elements
39983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Initialize the new FixedDoubleArray. Leave elements unitialized for
39993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // efficiency, they are guaranteed to be initialized before use.
40003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(FieldOperand(edi, JSObject::kMapOffset),
40013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Immediate(masm->isolate()->factory()->fixed_double_array_map()));
40023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(FieldOperand(edi, FixedDoubleArray::kLengthOffset),
40033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Immediate(Smi::FromInt(JSArray::kPreallocatedArrayElements)));
40043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Install the new backing store in the JSArray.
40063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(FieldOperand(edx, JSObject::kElementsOffset), edi);
40073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteField(edx, JSObject::kElementsOffset, edi, ebx,
40083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
40093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Increment the length of the array.
40113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(FieldOperand(edx, JSArray::kLengthOffset),
40123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Immediate(Smi::FromInt(1)));
40133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
40143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&finish_store);
40153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&check_capacity);
40173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // eax: value
40183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // ecx: key
40193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // edx: receiver
40203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // edi: elements
40213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure that the backing store can hold additional elements.
40223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(ecx, FieldOperand(edi, FixedDoubleArray::kLengthOffset));
40233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(above_equal, &slow);
40243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Grow the array and finish the store.
40263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(FieldOperand(edx, JSArray::kLengthOffset),
40273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Immediate(Smi::FromInt(1)));
40283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&finish_store);
40293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&prepare_slow);
40313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Restore the key, which is known to be the array length.
40323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(ecx, Immediate(0));
40333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&slow);
40353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
40363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(ic_slow, RelocInfo::CODE_TARGET);
40373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
40383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
40393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
40403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __
4042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
4044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
4045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_IA32
4046