ic-ia32.cc revision 7f4d5bd8c03935e2c0cd412e561b8fc5a6a880ae
17f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Copyright 2010 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 "codegen-inl.h"
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "ic-inl.h"
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "runtime.h"
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "stub-cache.h"
36d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "utils.h"
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Static IC stub generators.
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm)
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper function used to load a property from a dictionary backing storage.
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This function may return false negatives, so miss_label
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// must always call a backup property load that is complete.
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This function is safe to call if the receiver has fast properties,
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// or if name is not a symbol, and will jump to the miss_label in that case.
53e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkestatic void GenerateDictionaryLoad(MacroAssembler* masm,
54e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                   Label* miss_label,
55402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                   Register receiver,
56402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                   Register name,
57e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                   Register r0,
58e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                   Register r1,
59e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                   Register r2,
607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   Register result,
61e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                   DictionaryCheck check_dictionary) {
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register use:
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
64402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // name - holds the name of the property and is unchanged.
65402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // receiver - holds the receiver and is unchanged.
66402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Scratch registers:
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0   - used to hold the property dictionary.
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
69402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // r1   - used for the index into the property dictionary
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2   - used to hold the capacity of the property dictionary.
727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //
737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // result - holds the result on exit.
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label done;
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for the absence of an interceptor.
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the map into r0.
79402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(r0, FieldOperand(receiver, JSObject::kMapOffset));
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Bail out if the receiver has a named interceptor.
826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ test(FieldOperand(r0, Map::kBitFieldOffset),
836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          Immediate(1 << Map::kHasNamedInterceptor));
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_zero, miss_label, not_taken);
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Bail out if we have a JS global proxy object.
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movzx_b(r0, FieldOperand(r0, Map::kInstanceTypeOffset));
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, JS_GLOBAL_PROXY_TYPE);
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(equal, miss_label, not_taken);
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Possible work-around for http://crbug.com/16276.
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, JS_GLOBAL_OBJECT_TYPE);
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(equal, miss_label, not_taken);
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, JS_BUILTINS_OBJECT_TYPE);
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(equal, miss_label, not_taken);
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
97e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Load properties array.
98402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(r0, FieldOperand(receiver, JSObject::kPropertiesOffset));
99e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
100e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Check that the properties array is a dictionary.
101e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (check_dictionary == CHECK_DICTIONARY) {
102e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ cmp(FieldOperand(r0, HeapObject::kMapOffset),
103e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke           Immediate(Factory::hash_table_map()));
104e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ j(not_equal, miss_label);
105e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute the capacity mask.
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kCapacityOffset =
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      StringDictionary::kHeaderSize +
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      StringDictionary::kCapacityIndex * kPointerSize;
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r2, FieldOperand(r0, kCapacityOffset));
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ shr(r2, kSmiTagSize);  // convert smi to int
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ dec(r2);
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Generate an unrolled loop that performs a few probes before
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // giving up. Measurements done on Gmail indicate that 2 probes
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // cover ~93% of loads from dictionaries.
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kProbes = 4;
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kElementsStartOffset =
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      StringDictionary::kHeaderSize +
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      StringDictionary::kElementsStartIndex * kPointerSize;
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < kProbes; i++) {
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Compute the masked index: (hash + i + i * i) & mask.
124d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ mov(r1, FieldOperand(name, String::kHashFieldOffset));
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ shr(r1, String::kHashShift);
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (i > 0) {
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ add(Operand(r1), Immediate(StringDictionary::GetProbeOffset(i)));
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ and_(r1, Operand(r2));
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Scale the index by multiplying by the entry size.
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(StringDictionary::kEntrySize == 3);
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ lea(r1, Operand(r1, r1, times_2, 0));  // r1 = r1 * 3
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Check if the key is identical to the name.
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(name,
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           Operand(r0, r1, times_4, kElementsStartOffset - kHeapObjectTag));
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (i != kProbes - 1) {
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ j(equal, &done, taken);
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ j(not_equal, miss_label, not_taken);
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the value is a normal property.
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&done);
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ test(Operand(r0, r1, times_4, kDetailsOffset - kHeapObjectTag),
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize));
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_zero, miss_label, not_taken);
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the value at the masked, scaled index.
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kValueOffset = kElementsStartOffset + kPointerSize;
1547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(result, Operand(r0, r1, times_4, kValueOffset - kHeapObjectTag));
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1586ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void GenerateNumberDictionaryLoad(MacroAssembler* masm,
1596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                         Label* miss,
1606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                         Register elements,
1616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                         Register key,
1626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                         Register r0,
1636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                         Register r1,
1647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                         Register r2,
1657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                         Register result) {
1666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Register use:
1676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //
1686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // elements - holds the slow-case elements of the receiver and is unchanged.
1696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //
1707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // key      - holds the smi key on entry and is unchanged.
1716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //
1726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Scratch registers:
1736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //
1746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // r0 - holds the untagged key on entry and holds the hash once computed.
1756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //
1766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // r1 - used to hold the capacity mask of the dictionary
1776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //
1786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // r2 - used for the index into the dictionary.
1797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //
1807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // result - holds the result on exit if the load succeeds and we fall through.
1817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label done;
1836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Compute the hash code from the untagged key.  This must be kept in sync
1856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // with ComputeIntegerHash in utils.h.
1866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //
1876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // hash = ~hash + (hash << 15);
1886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(r1, r0);
1896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ not_(r0);
1906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ shl(r1, 15);
1916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ add(r0, Operand(r1));
1926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // hash = hash ^ (hash >> 12);
1936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(r1, r0);
1946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ shr(r1, 12);
1956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ xor_(r0, Operand(r1));
1966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // hash = hash + (hash << 2);
1976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ lea(r0, Operand(r0, r0, times_4, 0));
1986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // hash = hash ^ (hash >> 4);
1996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(r1, r0);
2006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ shr(r1, 4);
2016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ xor_(r0, Operand(r1));
2026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // hash = hash * 2057;
2036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ imul(r0, r0, 2057);
2046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // hash = hash ^ (hash >> 16);
2056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(r1, r0);
2066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ shr(r1, 16);
2076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ xor_(r0, Operand(r1));
2086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Compute capacity mask.
2106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(r1, FieldOperand(elements, NumberDictionary::kCapacityOffset));
2116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ shr(r1, kSmiTagSize);  // convert smi to int
2126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ dec(r1);
2136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Generate an unrolled loop that performs a few probes before giving up.
2156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int kProbes = 4;
2166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = 0; i < kProbes; i++) {
2176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Use r2 for index calculations and keep the hash intact in r0.
2186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ mov(r2, r0);
2196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Compute the masked index: (hash + i + i * i) & mask.
2206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (i > 0) {
2216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ add(Operand(r2), Immediate(NumberDictionary::GetProbeOffset(i)));
2226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ and_(r2, Operand(r1));
2246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Scale the index by multiplying by the entry size.
2266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(NumberDictionary::kEntrySize == 3);
2276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ lea(r2, Operand(r2, r2, times_2, 0));  // r2 = r2 * 3
2286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Check if the key matches.
2306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ cmp(key, FieldOperand(elements,
2316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             r2,
2326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             times_pointer_size,
2336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             NumberDictionary::kElementsStartOffset));
2346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (i != (kProbes - 1)) {
2356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ j(equal, &done, taken);
2366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
2376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ j(not_equal, miss, not_taken);
2386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&done);
2426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the value is a normal propety.
2436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int kDetailsOffset =
2446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      NumberDictionary::kElementsStartOffset + 2 * kPointerSize;
2456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT_EQ(NORMAL, 0);
2466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
2476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize));
2486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ j(not_zero, miss);
2496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Get the value at the masked, scaled index.
2516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int kValueOffset =
2526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      NumberDictionary::kElementsStartOffset + kPointerSize;
2537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset));
2546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
2556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The offset from the inlined patch site to the start of the
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// inlined load instruction.  It is 7 bytes (test eax, imm) plus
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6 bytes (jne slow_label).
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int LoadIC::kOffsetToLoadInstruction = 13;
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateArrayLength(MacroAssembler* masm) {
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
265402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : receiver
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StubCompiler::GenerateLoadArrayLength(masm, eax, edx, &miss);
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateStringLength(MacroAssembler* masm) {
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
279402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : receiver
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
285402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  StubCompiler::GenerateLoadStringLength(masm, eax, edx, ebx, &miss);
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
293402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : receiver
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StubCompiler::GenerateLoadFunctionPrototype(masm, eax, edx, ebx, &miss);
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Checks the receiver for special cases (value type, slow case bits).
3067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Falls through for regular JS object.
3077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
3087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                           Register receiver,
3097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                           Register r0,
3107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                           Label* slow) {
3117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Register use:
3127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //   receiver - holds the receiver and is unchanged.
3137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Scratch registers:
3147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //   r0 - used to hold the map of the receiver.
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object isn't a smi.
3177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ test(receiver, Immediate(kSmiTagMask));
3187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ j(zero, slow, not_taken);
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the map of the receiver.
3217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset));
322d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
323d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Check bit field.
3247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ test_b(FieldOperand(r0, Map::kBitFieldOffset),
3257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            KeyedLoadIC::kSlowCaseBitFieldMask);
3267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ j(not_zero, slow, not_taken);
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object is some kind of JS object EXCEPT JS Value type.
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // In the case that the object is a value-wrapper object,
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // we enter the runtime system to make sure that indexing
3307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // into string objects works as intended.
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
3327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ CmpInstanceType(r0, JS_OBJECT_TYPE);
3347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ j(below, slow, not_taken);
3357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
3367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Loads an indexed element from a fast case array.
3397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void GenerateFastArrayLoad(MacroAssembler* masm,
3407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  Register receiver,
3417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  Register key,
3427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  Register scratch,
3437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  Register result,
3447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  Label* not_fast_array,
3457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  Label* out_of_range) {
3467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Register use:
3477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //   receiver - holds the receiver and is unchanged.
3487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //   key - holds the key and is unchanged (must be a smi).
3497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Scratch registers:
3507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //   scratch - used to hold elements of the receiver and the loaded value.
3517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //   result - holds the result on exit if the load succeeds and
3527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //            we fall through.
3537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(scratch, FieldOperand(receiver, JSObject::kElementsOffset));
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object is in fast mode (not dictionary).
3567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ CheckMap(scratch, Factory::fixed_array_map(), not_fast_array, true);
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the key (index) is within bounds.
3587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ cmp(key, FieldOperand(scratch, FixedArray::kLengthOffset));
3597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ j(above_equal, out_of_range);
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fast case: Do the load.
3617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0));
3627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(scratch, FieldOperand(scratch, key, times_2, FixedArray::kHeaderSize));
3637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ cmp(Operand(scratch), Immediate(Factory::the_hole_value()));
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // In case the loaded value is the_hole we have to consult GetProperty
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to ensure the prototype chain is searched.
3667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ j(equal, out_of_range);
3677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (!result.is(scratch)) {
3687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ mov(result, scratch);
3697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
3707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
3717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Checks whether a key is an array index string or a symbol string.
3747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Falls through if a key is a symbol.
3757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void GenerateKeyStringCheck(MacroAssembler* masm,
3767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   Register key,
3777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   Register map,
3787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   Register hash,
3797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   Label* index_string,
3807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   Label* not_symbol) {
3817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Register use:
3827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //   key - holds the key and is unchanged. Assumed to be non-smi.
3837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Scratch registers:
3847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //   map - used to hold the map of the key.
3857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //   hash - used to hold the hash of the key.
3867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ CmpObjectType(key, FIRST_NONSTRING_TYPE, map);
3877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ j(above_equal, not_symbol);
3887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Is the string an array index, with cached numeric value?
3907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(hash, FieldOperand(key, String::kHashFieldOffset));
3917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ test(hash, Immediate(String::kContainsCachedArrayIndexMask));
3927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ j(zero, index_string, not_taken);
3937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Is the string a symbol?
3957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(kSymbolTag != 0);
3967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsSymbolMask);
3977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ j(zero, not_symbol, not_taken);
3987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
3997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
4007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
4017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Picks out an array index from the hash field.
4027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// The generated code never falls through.
4037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void GenerateIndexFromHash(MacroAssembler* masm,
4047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  Register key,
4057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  Register hash,
4067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  Label* index_smi) {
4077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Register use:
4087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //   key - holds the overwritten key on exit.
4097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //   hash - holds the key's hash. Clobbered.
4107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
4117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // The assert checks that the constants for the maximum number of digits
4127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // for an array index cached in the hash field and the number of bits
4137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // reserved for it does not conflict.
4147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
4157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch         (1 << String::kArrayIndexValueBits));
4167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // We want the smi-tagged index in key.  kArrayIndexValueMask has zeros in
4177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // the low kHashShift bits.
4187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // key: string key
4197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // ebx: hash field.
4207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(String::kHashShift >= kSmiTagSize);
4217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ and_(hash, String::kArrayIndexValueMask);
4227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ shr(hash, String::kHashShift - kSmiTagSize);
4237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Here we actually clobber the key which will be used if calling into
4247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // runtime later. However as the new key is the numeric value of a string key
4257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // there is no difference in using either key.
4267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(key, hash);
4277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Now jump to the place where smi keys are handled.
4287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(index_smi);
4297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
4307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
4317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
4327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
4337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // ----------- S t a t e -------------
4347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- eax    : key
4357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- edx    : receiver
4367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[0] : return address
4377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // -----------------------------------
4387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label slow, check_string, index_smi, index_string;
4397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label check_pixel_array, probe_dictionary, check_number_dictionary;
4407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
4417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateKeyedLoadReceiverCheck(masm, edx, ecx, &slow);
4427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
4437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Check that the key is a smi.
4447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ test(eax, Immediate(kSmiTagMask));
4457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ j(not_zero, &check_string, not_taken);
4467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_smi);
4477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Now the key is known to be a smi. This place is also jumped to from
4487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // where a numeric string is converted to a smi.
4497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
4507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateFastArrayLoad(masm,
4517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                        edx,
4527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                        eax,
4537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                        ecx,
4547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                        eax,
4557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                        &check_pixel_array,
4567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                        &slow);
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::keyed_load_generic_smi, 1);
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&check_pixel_array);
461402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Check whether the elements is a pixel array.
462402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // edx: receiver
463402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // eax: key
464402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // ecx: elements
4657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(ebx, eax);
4667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ SmiUntag(ebx);
4676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ CheckMap(ecx, Factory::pixel_array_map(), &check_number_dictionary, true);
468402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ cmp(ebx, FieldOperand(ecx, PixelArray::kLengthOffset));
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(above_equal, &slow);
470402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(eax, FieldOperand(ecx, PixelArray::kExternalPointerOffset));
471402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ movzx_b(eax, Operand(eax, ebx, times_1, 0));
472402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ SmiTag(eax);
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&check_number_dictionary);
4766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check whether the elements is a number dictionary.
4776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // edx: receiver
4786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ebx: untagged index
4796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // eax: key
4806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ecx: elements
4816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ CheckMap(ecx, Factory::hash_table_map(), &slow, true);
4826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label slow_pop_receiver;
4836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Push receiver on the stack to free up a register for the dictionary
4846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // probing.
4856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(edx);
4866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  GenerateNumberDictionaryLoad(masm,
4876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               &slow_pop_receiver,
4886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               ecx,
4896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               eax,
4906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               ebx,
4916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               edx,
4927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                               edi,
4937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                               eax);
4946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Pop receiver before returning.
4956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ pop(edx);
4966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ret(0);
4976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&slow_pop_receiver);
4996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Pop the receiver from the stack and jump to runtime.
5006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ pop(edx);
5016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&slow);
503402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Slow case: jump to runtime.
504402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // edx: receiver
505402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // eax: key
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::keyed_load_generic_slow, 1);
507402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateRuntimeGetProperty(masm);
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&check_string);
5107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateKeyStringCheck(masm, eax, ecx, ebx, &index_string, &slow);
511e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
512e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // If the receiver is a fast-case object, check the keyed lookup
513402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // cache. Otherwise probe the dictionary.
514402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset));
515e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
516e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke         Immediate(Factory::hash_table_map()));
517e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, &probe_dictionary);
518e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
519e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Load the map of the receiver, compute the keyed lookup cache hash
520e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // based on 32 bits of the map pointer and the string hash.
521402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
522402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(ecx, ebx);
523402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ shr(ecx, KeyedLookupCache::kMapHashShift);
524402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(edi, FieldOperand(eax, String::kHashFieldOffset));
525402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ shr(edi, String::kHashShift);
526402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ xor_(ecx, Operand(edi));
527402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ and_(ecx, KeyedLookupCache::kCapacityMask);
528e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
529e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Load the key (consisting of map and symbol) from the cache and
530e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // check for match.
531e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ExternalReference cache_keys
532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      = ExternalReference::keyed_lookup_cache_keys();
533402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(edi, ecx);
534e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ shl(edi, kPointerSizeLog2 + 1);
535e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys));
536e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(not_equal, &slow);
537e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ add(Operand(edi), Immediate(kPointerSize));
538402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ cmp(eax, Operand::StaticArray(edi, times_1, cache_keys));
539e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(not_equal, &slow);
540e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
541e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Get field offset and check that it is an in-object property.
542402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // edx     : receiver
543402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // ebx     : receiver's map
544402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // eax     : key
545402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // ecx     : lookup cache index
546e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ExternalReference cache_field_offsets
547e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      = ExternalReference::keyed_lookup_cache_field_offsets();
548402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(edi,
549402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu         Operand::StaticArray(ecx, times_pointer_size, cache_field_offsets));
550402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ movzx_b(ecx, FieldOperand(ebx, Map::kInObjectPropertiesOffset));
5517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ sub(edi, Operand(ecx));
552e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(above_equal, &slow);
553e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
554e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Load in-object property.
555402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset));
556402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ add(ecx, Operand(edi));
557402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(eax, FieldOperand(edx, ecx, times_pointer_size, 0));
5587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ IncrementCounter(&Counters::keyed_load_generic_lookup_cache, 1);
559e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ ret(0);
560e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
561e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Do a quick inline probe of the receiver's dictionary, if it
562e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // exists.
563e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ bind(&probe_dictionary);
564e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  GenerateDictionaryLoad(masm,
565e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                         &slow,
566e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                         edx,
567e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                         eax,
568402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                         ebx,
569402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                         ecx,
570402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                         edi,
5717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                         eax,
572e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                         DICTIONARY_CHECK_DONE);
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1);
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
575e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&index_string);
5777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateIndexFromHash(masm, eax, ebx, &index_smi);
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
581e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid KeyedLoadIC::GenerateString(MacroAssembler* masm) {
582e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // ----------- S t a t e -------------
5836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- eax    : key (index)
584402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
585e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[0] : return address
586e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // -----------------------------------
5876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss;
5886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label index_out_of_range;
5896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register receiver = edx;
5916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register index = eax;
5927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register scratch1 = ebx;
5937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register scratch2 = ecx;
5947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = eax;
5957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
5967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharAtGenerator char_at_generator(receiver,
5977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                          index,
5987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                          scratch1,
5997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                          scratch2,
6007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                          result,
6017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                          &miss,  // When not a string.
6027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                          &miss,  // When not a number.
6037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                          &index_out_of_range,
6047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                          STRING_INDEX_IS_ARRAY_INDEX);
6057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  char_at_generator.GenerateFast(masm);
6067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ ret(0);
6077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
6087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ICRuntimeCallHelper call_helper;
6097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  char_at_generator.GenerateSlow(masm, call_helper);
610e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
6116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&index_out_of_range);
6126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ Set(eax, Immediate(Factory::undefined_value()));
6136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ret(0);
614e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
615e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ bind(&miss);
616e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  GenerateMiss(masm);
617e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
619e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
6203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm,
6213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                        ExternalArrayType array_type) {
6223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // ----------- S t a t e -------------
623402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
624402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
6253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  //  -- esp[0] : return address
6263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // -----------------------------------
6273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label slow, failed_allocation;
6283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Check that the object isn't a smi.
630402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ test(edx, Immediate(kSmiTagMask));
6313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(zero, &slow, not_taken);
6323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Check that the key is a smi.
6343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ test(eax, Immediate(kSmiTagMask));
6353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_zero, &slow, not_taken);
6363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Get the map of the receiver.
638402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
6393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Check that the receiver does not require access checks.  We need
6403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // to check this explicitly since this generic stub does not perform
6413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // map checks.
6427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ test_b(FieldOperand(ecx, Map::kBitFieldOffset),
6437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            1 << Map::kIsAccessCheckNeeded);
6443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_zero, &slow, not_taken);
6453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
646402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ CmpInstanceType(ecx, JS_OBJECT_TYPE);
6473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, &slow, not_taken);
6483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Check that the elements array is the appropriate type of
6503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // ExternalArray.
651402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
6523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Handle<Map> map(Heap::MapForExternalArrayType(array_type));
653402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
6543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block         Immediate(map));
6553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, &slow, not_taken);
6563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
657402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // eax: key, known to be a smi.
658402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // edx: receiver, known to be a JSObject.
659402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // ebx: elements object, known to be an external array.
6603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Check that the index is in range.
661402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(ecx, eax);
662402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ SmiUntag(ecx);  // Untag the index.
663402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset));
6643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Unsigned comparison catches both negative and too-large values.
6653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(above_equal, &slow);
6663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
667402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset));
668402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // ebx: base pointer of external storage
6693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  switch (array_type) {
6703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    case kExternalByteArray:
671402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ movsx_b(ecx, Operand(ebx, ecx, times_1, 0));
6723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      break;
6733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    case kExternalUnsignedByteArray:
674402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ movzx_b(ecx, Operand(ebx, ecx, times_1, 0));
6753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      break;
6763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    case kExternalShortArray:
677402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ movsx_w(ecx, Operand(ebx, ecx, times_2, 0));
6783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      break;
6793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    case kExternalUnsignedShortArray:
680402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ movzx_w(ecx, Operand(ebx, ecx, times_2, 0));
6813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      break;
6823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    case kExternalIntArray:
6833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    case kExternalUnsignedIntArray:
684402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ mov(ecx, Operand(ebx, ecx, times_4, 0));
6853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      break;
6863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    case kExternalFloatArray:
687402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ fld_s(Operand(ebx, ecx, times_4, 0));
6883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      break;
6893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    default:
6903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      UNREACHABLE();
6913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      break;
6923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
6933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // For integer array types:
695402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // ecx: value
6963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // For floating-point array type:
6973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // FP(0): value
6983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (array_type == kExternalIntArray ||
7003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      array_type == kExternalUnsignedIntArray) {
7013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // For the Int and UnsignedInt array types, we need to see whether
7023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // the value can be represented in a Smi. If not, we need to convert
7033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // it to a HeapNumber.
7043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label box_int;
7053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (array_type == kExternalIntArray) {
706402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ cmp(ecx, 0xC0000000);
707402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ j(sign, &box_int);
7083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    } else {
7093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      ASSERT_EQ(array_type, kExternalUnsignedIntArray);
7103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      // The test is different for unsigned int values. Since we need
711402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      // the value to be in the range of a positive smi, we can't
7123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      // handle either of the top two bits being set in the value.
713402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ test(ecx, Immediate(0xC0000000));
7143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ j(not_zero, &box_int);
7153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
7163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
717402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ mov(eax, ecx);
718402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ SmiTag(eax);
7193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ ret(0);
7203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ bind(&box_int);
7223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Allocate a HeapNumber for the int and perform int-to-double
7243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // conversion.
7253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (array_type == kExternalIntArray) {
726402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ push(ecx);
7273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ fild_s(Operand(esp, 0));
728402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ pop(ecx);
7293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    } else {
7303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      ASSERT(array_type == kExternalUnsignedIntArray);
7313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      // Need to zero-extend the value.
7323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      // There's no fild variant for unsigned values, so zero-extend
7333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      // to a 64-bit int manually.
7343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ push(Immediate(0));
735402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ push(ecx);
7363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ fild_d(Operand(esp, 0));
737402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ pop(ecx);
738402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      __ pop(ecx);
7393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
7403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // FP(0): value
741402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation);
7423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Set the value.
743402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ mov(eax, ecx);
7443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
7453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ ret(0);
7463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (array_type == kExternalFloatArray) {
7473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // For the floating-point array type, we need to always allocate a
7483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // HeapNumber.
749402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation);
7503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Set the value.
751402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ mov(eax, ecx);
7523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
7533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ ret(0);
7543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
755402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ mov(eax, ecx);
756402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ SmiTag(eax);
7573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ ret(0);
7583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
7593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // If we fail allocation of the HeapNumber, we still have a value on
7613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // top of the FPU stack. Remove it.
7623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&failed_allocation);
7633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ffree();
7643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ fincstp();
7653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Fall through to slow case.
7663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Slow case: Jump to runtime.
7683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&slow);
7693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1);
770402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateRuntimeGetProperty(masm);
771402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
772402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
773402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
774402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
775402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // ----------- S t a t e -------------
776402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
777402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
778402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- esp[0] : return address
779402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // -----------------------------------
780402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Label slow;
781402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
782402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Check that the receiver isn't a smi.
783402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ test(edx, Immediate(kSmiTagMask));
784402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ j(zero, &slow, not_taken);
785402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
786402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Check that the key is a smi.
787402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ test(eax, Immediate(kSmiTagMask));
788402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ j(not_zero, &slow, not_taken);
789402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
790402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Get the map of the receiver.
791402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
792402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
793402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Check that it has indexed interceptor and access checks
794402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // are not enabled for this object.
795402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ movzx_b(ecx, FieldOperand(ecx, Map::kBitFieldOffset));
796402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ and_(Operand(ecx), Immediate(kSlowCaseBitFieldMask));
797402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ cmp(Operand(ecx), Immediate(1 << Map::kHasIndexedInterceptor));
798402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ j(not_zero, &slow, not_taken);
799402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
800402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Everything is fine, call runtime.
801402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ pop(ecx);
802402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(edx);  // receiver
803402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(eax);  // key
804402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(ecx);  // return address
805402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
806402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Perform tail call to the entry.
8076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ExternalReference ref = ExternalReference(
8086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      IC_Utility(kKeyedLoadPropertyWithInterceptor));
8096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallExternalReference(ref, 2, 1);
810402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
811402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ bind(&slow);
812402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateMiss(masm);
8133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
8143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- eax    : value
8196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ecx    : key
8206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- edx    : receiver
821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label slow, fast, array, extra, check_pixel_array;
824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object isn't a smi.
826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ test(edx, Immediate(kSmiTagMask));
827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(zero, &slow, not_taken);
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the map from the receiver.
8296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver does not require access checks.  We need
831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to do this because this generic stub does not perform map checks.
8327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ test_b(FieldOperand(edi, Map::kBitFieldOffset),
8337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            1 << Map::kIsAccessCheckNeeded);
834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_zero, &slow, not_taken);
835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the key is a smi.
8366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ test(ecx, Immediate(kSmiTagMask));
837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_zero, &slow, not_taken);
8386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ CmpInstanceType(edi, JS_ARRAY_TYPE);
839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(equal, &array);
840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object is some kind of JS object.
8416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE);
8426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ j(below, &slow, not_taken);
843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Object case: Check key against length in the elements array.
845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // eax: value
846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // edx: JSObject
8476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ecx: key (a smi)
8486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object is in fast mode (not dictionary).
8506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true);
8517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset));
852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(below, &fast, taken);
853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Slow case: call runtime.
855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&slow);
856402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateRuntimeSetProperty(masm);
857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check whether the elements is a pixel array.
859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&check_pixel_array);
8606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // eax: value
8617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // ecx: key (a smi)
8626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // edx: receiver
8636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // edi: elements array
8646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ CheckMap(edi, Factory::pixel_array_map(), &slow, true);
865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the value is a smi. If a conversion is needed call into the
866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // runtime to convert and clamp.
867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ test(eax, Immediate(kSmiTagMask));
868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_zero, &slow);
8696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(ebx, ecx);
8706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ SmiUntag(ebx);
8716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ cmp(ebx, FieldOperand(edi, PixelArray::kLengthOffset));
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(above_equal, &slow);
8736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(ecx, eax);  // Save the value. Key is not longer needed.
8746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ SmiUntag(ecx);
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {  // Clamp the value to [0..255].
8763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label done;
8776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ test(ecx, Immediate(0xFFFFFF00));
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ j(zero, &done);
8796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ setcc(negative, ecx);  // 1 if negative, 0 if positive.
8806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ dec_b(ecx);  // 0 if negative, 255 if positive.
881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&done);
882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
8836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(edi, FieldOperand(edi, PixelArray::kExternalPointerOffset));
8846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
8856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ret(0);  // Return value in eax.
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Extra capacity case: Check if there is extra capacity to
888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // perform the store and update the length. Used for adding one
889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // element to the array by writing to array[array.length].
890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&extra);
891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // eax: value
8926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // edx: receiver, a JSArray
8936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ecx: key, a smi.
8946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // edi: receiver->elements, a FixedArray
8956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // flags: compare (ecx, edx.length())
896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &slow, not_taken);  // do not leave holes in the array
8977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset));
898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(above_equal, &slow, not_taken);
8996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Add 1 to receiver->length, and go to fast array write.
9006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ add(FieldOperand(edx, JSArray::kLengthOffset),
9017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch         Immediate(Smi::FromInt(1)));
902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(&fast);
903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Array case: Get the length and the elements array from the JS
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // array. Check that the array is in fast mode; if it is the
906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // length is always a smi.
907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&array);
908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // eax: value
9096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // edx: receiver, a JSArray
9106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ecx: key, a smi.
9116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
9126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true);
913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the key against the length in the array, compute the
915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // address to store into and fall through to fast case.
9166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset));  // Compare smis.
917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(above_equal, &extra, not_taken);
918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fast case: Do the store.
920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&fast);
921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // eax: value
9226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ecx: key (a smi)
9236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // edx: receiver
9246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // edi: FixedArray receiver->elements
92525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  __ mov(CodeGenerator::FixedArrayElementOperand(edi, ecx), eax);
926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update write barrier for the elements array address.
927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(edx, Operand(eax));
9286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ RecordWrite(edi, 0, edx, ecx);
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm,
9343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                         ExternalArrayType array_type) {
9353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // ----------- S t a t e -------------
9363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  //  -- eax    : value
9376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ecx    : key
9386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- edx    : receiver
9393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  //  -- esp[0] : return address
9403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // -----------------------------------
9413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Label slow, check_heap_number;
9423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Check that the object isn't a smi.
9443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ test(edx, Immediate(kSmiTagMask));
9453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(zero, &slow);
9463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Get the map from the receiver.
9476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
9483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Check that the receiver does not require access checks.  We need
9493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // to do this because this generic stub does not perform map checks.
9507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ test_b(FieldOperand(edi, Map::kBitFieldOffset),
9517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            1 << Map::kIsAccessCheckNeeded);
9523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_zero, &slow);
9533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Check that the key is a smi.
9546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ test(ecx, Immediate(kSmiTagMask));
9553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_zero, &slow);
9563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Get the instance type from the map of the receiver.
9576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ CmpInstanceType(edi, JS_OBJECT_TYPE);
9583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, &slow);
9593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Check that the elements array is the appropriate type of
9613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // ExternalArray.
9623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // eax: value
9636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // edx: receiver, a JSObject
9646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ecx: key, a smi
9656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
9666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ CheckMap(edi, Handle<Map>(Heap::MapForExternalArrayType(array_type)),
9676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              &slow, true);
9683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Check that the index is in range.
9706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(ebx, ecx);
9716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ SmiUntag(ebx);
9726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ cmp(ebx, FieldOperand(edi, ExternalArray::kLengthOffset));
9733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Unsigned comparison catches both negative and too-large values.
9743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(above_equal, &slow);
9753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
9763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Handle both smis and HeapNumbers in the fast path. Go to the
9773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // runtime for all other kinds of values.
9783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // eax: value
9796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // edx: receiver
9806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ecx: key
9816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // edi: elements array
9823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // ebx: untagged index
9833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ test(eax, Immediate(kSmiTagMask));
9843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, &check_heap_number);
9853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // smi case
9866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(ecx, eax);  // Preserve the value in eax.  Key is no longer needed.
9876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ SmiUntag(ecx);
9886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
9893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // ecx: base pointer of external storage
9903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  switch (array_type) {
9913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    case kExternalByteArray:
9923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    case kExternalUnsignedByteArray:
9936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
9943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      break;
9953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    case kExternalShortArray:
9963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    case kExternalUnsignedShortArray:
9976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ mov_w(Operand(edi, ebx, times_2, 0), ecx);
9983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      break;
9993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    case kExternalIntArray:
10003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    case kExternalUnsignedIntArray:
10016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ mov(Operand(edi, ebx, times_4, 0), ecx);
10023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      break;
10033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    case kExternalFloatArray:
10043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      // Need to perform int-to-float conversion.
10056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ push(ecx);
10063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ fild_s(Operand(esp, 0));
10076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ pop(ecx);
10086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ fstp_s(Operand(edi, ebx, times_4, 0));
10093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      break;
10103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    default:
10113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      UNREACHABLE();
10123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      break;
10133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
10146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ret(0);  // Return the original value.
10153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&check_heap_number);
10176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // eax: value
10186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // edx: receiver
10196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ecx: key
10206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // edi: elements array
10216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ebx: untagged index
10223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
10233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block         Immediate(Factory::heap_number_map()));
10243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(not_equal, &slow);
10253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // The WebGL specification leaves the behavior of storing NaN and
10273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // +/-Infinity into integer arrays basically undefined. For more
10283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // reproducible behavior, convert these to zero.
10293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
10306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
10313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // ebx: untagged index
10326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // edi: base pointer of external storage
10333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // top of FPU stack: value
10343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (array_type == kExternalFloatArray) {
10356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ fstp_s(Operand(edi, ebx, times_4, 0));
10363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ ret(0);
10373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
10383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Need to perform float-to-int conversion.
10393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Test the top of the FP stack for NaN.
10403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Label is_nan;
10413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ fucomi(0);
10423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ j(parity_even, &is_nan);
10433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (array_type != kExternalUnsignedIntArray) {
10456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ push(ecx);  // Make room on stack
10463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ fistp_s(Operand(esp, 0));
10476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ pop(ecx);
10483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    } else {
10493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      // fistp stores values as signed integers.
10503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      // To represent the entire range, we need to store as a 64-bit
10513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      // int and discard the high 32 bits.
10526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ sub(Operand(esp), Immediate(2 * kPointerSize));
10533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      __ fistp_d(Operand(esp, 0));
10546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ pop(ecx);
10556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ add(Operand(esp), Immediate(kPointerSize));
10563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
10576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // ecx: untagged integer value
10583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    switch (array_type) {
10593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      case kExternalByteArray:
10603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      case kExternalUnsignedByteArray:
10616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
10623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        break;
10633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      case kExternalShortArray:
10643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      case kExternalUnsignedShortArray:
10656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        __ mov_w(Operand(edi, ebx, times_2, 0), ecx);
10663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        break;
10673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      case kExternalIntArray:
10683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      case kExternalUnsignedIntArray: {
10693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        // We also need to explicitly check for +/-Infinity. These are
10703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        // converted to MIN_INT, but we need to be careful not to
10713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        // confuse with legal uses of MIN_INT.
10723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        Label not_infinity;
10733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        // This test would apparently detect both NaN and Infinity,
10743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        // but we've already checked for NaN using the FPU hardware
10753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        // above.
10766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        __ mov_w(edx, FieldOperand(eax, HeapNumber::kValueOffset + 6));
10776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        __ and_(edx, 0x7FF0);
10786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        __ cmp(edx, 0x7FF0);
10793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        __ j(not_equal, &not_infinity);
10806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        __ mov(ecx, 0);
10813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        __ bind(&not_infinity);
10826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        __ mov(Operand(edi, ebx, times_4, 0), ecx);
10833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        break;
10843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      }
10853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      default:
10863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        UNREACHABLE();
10873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        break;
10883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
10896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ ret(0);  // Return original value.
10903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
10913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ bind(&is_nan);
10923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ ffree();
10933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    __ fincstp();
10943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    switch (array_type) {
10953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      case kExternalByteArray:
10963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      case kExternalUnsignedByteArray:
10976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        __ mov_b(Operand(edi, ebx, times_1, 0), 0);
10983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        break;
10993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      case kExternalShortArray:
11003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      case kExternalUnsignedShortArray:
11016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        __ xor_(ecx, Operand(ecx));
11026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        __ mov_w(Operand(edi, ebx, times_2, 0), ecx);
11033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        break;
11043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      case kExternalIntArray:
11053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      case kExternalUnsignedIntArray:
11066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        __ mov(Operand(edi, ebx, times_4, 0), Immediate(0));
11073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        break;
11083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      default:
11093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        UNREACHABLE();
11103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        break;
11113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    }
11126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ ret(0);  // Return the original value.
11133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
11143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Slow case: call runtime.
11163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&slow);
1117402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateRuntimeSetProperty(masm);
11183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
11193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Defined in ic.cc.
1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* CallIC_Miss(Arguments args);
1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// The generated code does not accept smi keys.
11257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// The generated code falls through if both probes miss.
11267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
11277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                          int argc,
11287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                          Code::Kind kind,
11297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                          Label* miss) {
1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1131e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ecx                 : name
11327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- edx                 : receiver
1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
11347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label number, non_number, non_string, boolean, probe;
1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Probe the stub cache.
1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Code::Flags flags =
11387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      Code::ComputeFlags(kind, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc);
1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, eax);
1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the stub cache probing failed, the receiver might be a value.
1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // For value objects, we use the map of the prototype objects for
1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the corresponding JSValue for the cache and that is what we need
1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to probe.
1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for number.
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ test(edx, Immediate(kSmiTagMask));
1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(zero, &number, not_taken);
1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ebx);
1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &non_number, taken);
1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&number);
1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StubCompiler::GenerateLoadGlobalFunctionPrototype(
1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      masm, Context::NUMBER_FUNCTION_INDEX, edx);
1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(&probe);
1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for string.
1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&non_number);
11587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ CmpInstanceType(ebx, FIRST_NONSTRING_TYPE);
1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(above_equal, &non_string, taken);
1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StubCompiler::GenerateLoadGlobalFunctionPrototype(
1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      masm, Context::STRING_FUNCTION_INDEX, edx);
1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(&probe);
1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for boolean.
1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&non_string);
1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(edx, Factory::true_value());
1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(equal, &boolean, not_taken);
1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(edx, Factory::false_value());
11697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ j(not_equal, miss, taken);
1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&boolean);
1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StubCompiler::GenerateLoadGlobalFunctionPrototype(
1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      masm, Context::BOOLEAN_FUNCTION_INDEX, edx);
1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Probe the stub cache for the value object.
1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&probe);
1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg);
1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GenerateNormalHelper(MacroAssembler* masm,
1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 int argc,
1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 bool is_global_object,
1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Label* miss) {
1184e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // ----------- S t a t e -------------
1185e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ecx                 : name
1186e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- edx                 : receiver
1187e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[0]              : return address
1188e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
1189e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ...
1190e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc + 1) * 4] : receiver
1191e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // -----------------------------------
1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1193e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Search dictionary - put result in register edi.
1194e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(edi, edx);
11957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateDictionaryLoad(
11967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      masm, miss, edx, ecx, eax, edi, ebx, edi, CHECK_DICTIONARY);
1197e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1198e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Check that the result is not a smi.
1199e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ test(edi, Immediate(kSmiTagMask));
1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(zero, miss, not_taken);
1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1202e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Check that the value is a JavaScript function, fetching its map into eax.
1203e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax);
1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, miss, not_taken);
1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1206e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Patch the receiver on stack with the global proxy if necessary.
1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (is_global_object) {
1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the function.
1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount actual(argc);
1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ InvokeFunction(edi, actual, JUMP_FUNCTION);
1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// The generated code never falls through.
12187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void GenerateCallNormal(MacroAssembler* masm, int argc, Label* miss) {
1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1220e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ecx                 : name
1221e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[0]              : return address
1222e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
1223e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ...
1224e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc + 1) * 4] : receiver
1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
12267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label global_object, non_global_object;
1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver of the function from the stack; 1 ~ return address.
1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ test(edx, Immediate(kSmiTagMask));
12337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ j(zero, miss, not_taken);
1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver is a valid JS object.
1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movzx_b(eax, FieldOperand(ebx, Map::kInstanceTypeOffset));
1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(eax, FIRST_JS_OBJECT_TYPE);
12397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ j(below, miss, not_taken);
1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If this assert fails, we have to check upper bound too.
1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for access to global object.
1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(eax, JS_GLOBAL_OBJECT_TYPE);
1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(equal, &global_object);
1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(eax, JS_BUILTINS_OBJECT_TYPE);
1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &non_global_object);
1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Accessing global object: Load and invoke.
1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&global_object);
1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the global object does not require access checks.
12537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ test_b(FieldOperand(ebx, Map::kBitFieldOffset),
12547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            1 << Map::kIsAccessCheckNeeded);
12557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ j(not_equal, miss, not_taken);
12567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateNormalHelper(masm, argc, true, miss);
1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Accessing non-global object: Check for access to global proxy.
1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label global_proxy, invoke;
1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&non_global_object);
1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(eax, JS_GLOBAL_PROXY_TYPE);
1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(equal, &global_proxy, not_taken);
1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the non-global, non-global-proxy object does not
1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // require access checks.
12657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ test_b(FieldOperand(ebx, Map::kBitFieldOffset),
12667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            1 << Map::kIsAccessCheckNeeded);
12677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ j(not_equal, miss, not_taken);
1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&invoke);
12697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateNormalHelper(masm, argc, false, miss);
1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Global object proxy access: Check access rights.
1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&global_proxy);
12737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ CheckAccessGlobalProxy(edx, eax, miss);
1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(&invoke);
1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) {
1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1280e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ecx                 : name
1281e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[0]              : return address
1282e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
1283e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ...
1284e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc + 1) * 4] : receiver
1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver of the function from the stack; 1 ~ return address.
1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Enter an internal frame.
1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ EnterInternalFrame();
1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Push the receiver and the name of the function.
1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(edx);
1295e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ push(ecx);
1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call the entry.
1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CEntryStub stub(1);
1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(eax, Immediate(2));
13007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(ebx, Immediate(ExternalReference(IC_Utility(id))));
1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CallStub(&stub);
1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move result to edi and exit the internal frame.
1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(edi, eax);
1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LeaveInternalFrame();
1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if the receiver is a global object of some sort.
1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label invoke, global;
1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));  // receiver
1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ test(edx, Immediate(kSmiTagMask));
1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(zero, &invoke, not_taken);
1312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
1313e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
1314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ cmp(ebx, JS_GLOBAL_OBJECT_TYPE);
1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(equal, &global);
1316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ cmp(ebx, JS_BUILTINS_OBJECT_TYPE);
1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &invoke);
1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the receiver on the stack.
1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&global);
1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the function.
1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount actual(argc);
1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&invoke);
1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ InvokeFunction(edi, actual, JUMP_FUNCTION);
1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
13327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // ----------- S t a t e -------------
13337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- ecx                 : name
13347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[0]              : return address
13357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
13367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- ...
13377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[(argc + 1) * 4] : receiver
13387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // -----------------------------------
13397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label miss;
13417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Get the receiver of the function from the stack; 1 ~ return address.
13427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
13437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC, &miss);
13447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&miss);
13457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateMiss(masm, argc);
13467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
13477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
13507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label miss;
13517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateCallNormal(masm, argc, &miss);
13527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&miss);
13537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateMiss(masm, argc);
13547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
13557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid CallIC::GenerateMiss(MacroAssembler* masm, int argc) {
13587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateCallMiss(masm, argc, IC::kCallIC_Miss);
13597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
13607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
13637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // ----------- S t a t e -------------
13647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- ecx                 : name
13657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[0]              : return address
13667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
13677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- ...
13687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[(argc + 1) * 4] : receiver
13697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // -----------------------------------
13707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Get the receiver of the function from the stack; 1 ~ return address.
13727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
13737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label do_call, slow_call, slow_load, slow_reload_receiver;
13757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label check_number_dictionary, check_string, lookup_monomorphic_cache;
13767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_smi, index_string;
13777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Check that the key is a smi.
13797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ test(ecx, Immediate(kSmiTagMask));
13807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ j(not_zero, &check_string, not_taken);
13817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_smi);
13837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Now the key is known to be a smi. This place is also jumped to from
13847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // where a numeric string is converted to a smi.
13857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateKeyedLoadReceiverCheck(masm, edx, eax, &slow_call);
13877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateFastArrayLoad(masm,
13897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                        edx,
13907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                        ecx,
13917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                        eax,
13927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                        edi,
13937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                        &check_number_dictionary,
13947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                        &slow_load);
13957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ IncrementCounter(&Counters::keyed_call_generic_smi_fast, 1);
13967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&do_call);
13987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // receiver in edx is not used after this point.
13997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // ecx: key
14007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // edi: function
14017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
14027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Check that the value in edi is a JavaScript function.
14037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ test(edi, Immediate(kSmiTagMask));
14047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ j(zero, &slow_call, not_taken);
14057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax);
14067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ j(not_equal, &slow_call, not_taken);
14077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Invoke the function.
14087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ParameterCount actual(argc);
14097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ InvokeFunction(edi, actual, JUMP_FUNCTION);
14107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
14117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&check_number_dictionary);
14127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // eax: elements
14137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // ecx: smi key
14147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Check whether the elements is a number dictionary.
14157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ CheckMap(eax, Factory::hash_table_map(), &slow_load, true);
14167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(ebx, ecx);
14177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ SmiUntag(ebx);
14187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // ebx: untagged index
14197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Receiver in edx will be clobbered, need to reload it on miss.
14207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateNumberDictionaryLoad(masm,
14217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                               &slow_reload_receiver,
14227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                               eax,
14237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                               ecx,
14247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                               ebx,
14257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                               edx,
14267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                               edi,
14277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                               edi);
14287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ IncrementCounter(&Counters::keyed_call_generic_smi_dict, 1);
14297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&do_call);
14307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
14317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&slow_reload_receiver);
14327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
14337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
14347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&slow_load);
14357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // This branch is taken when calling KeyedCallIC_Miss is neither required
14367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // nor beneficial.
14377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ IncrementCounter(&Counters::keyed_call_generic_slow_load, 1);
14387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ EnterInternalFrame();
14397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ push(ecx);  // save the key
14407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ push(edx);  // pass the receiver
14417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ push(ecx);  // pass the key
14427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ CallRuntime(Runtime::kKeyedGetProperty, 2);
14437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ pop(ecx);  // restore the key
14447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ LeaveInternalFrame();
14457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(edi, eax);
14467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&do_call);
14477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
14487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&check_string);
14497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateKeyStringCheck(masm, ecx, eax, ebx, &index_string, &slow_call);
14507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
14517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // The key is known to be a symbol.
14527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // If the receiver is a regular JS object with slow properties then do
14537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // a quick inline probe of the receiver's dictionary.
14547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Otherwise do the monomorphic cache probe.
14557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateKeyedLoadReceiverCheck(masm, edx, eax, &lookup_monomorphic_cache);
14567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
14577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset));
14587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
14597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch         Immediate(Factory::hash_table_map()));
14607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ j(not_equal, &lookup_monomorphic_cache, not_taken);
14617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
14627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateDictionaryLoad(masm,
14637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                         &slow_load,
14647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                         edx,
14657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                         ecx,
14667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                         ebx,
14677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                         eax,
14687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                         edi,
14697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                         edi,
14707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                         DICTIONARY_CHECK_DONE);
14717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ IncrementCounter(&Counters::keyed_call_generic_lookup_dict, 1);
14727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&do_call);
14737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
14747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&lookup_monomorphic_cache);
14757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ IncrementCounter(&Counters::keyed_call_generic_lookup_cache, 1);
14767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC, &slow_call);
14777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Fall through on miss.
14787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
14797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&slow_call);
14807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // This branch is taken if:
14817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // - the receiver requires boxing or access check,
14827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // - the key is neither smi nor symbol,
14837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // - the value loaded is not a function,
14847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // - there is hope that the runtime will create a monomorphic call stub
14857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //   that will get fetched next time.
14867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ IncrementCounter(&Counters::keyed_call_generic_slow, 1);
14877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateMiss(masm, argc);
14887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
14897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_string);
14907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateIndexFromHash(masm, ecx, ebx, &index_smi);
14917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
14927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
14937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
14947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) {
14957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label miss;
14967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateCallNormal(masm, argc, &miss);
14977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&miss);
14987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateMiss(masm, argc);
14997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
15007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
15017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
15027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) {
15037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss);
15047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
15057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
15067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Defined in ic.cc.
1508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* LoadIC_Miss(Arguments args);
1509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1512402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : receiver
1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
1515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Probe the stub cache.
1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC,
1519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                         NOT_IN_LOOP,
1520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                         MONOMORPHIC);
1521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StubCache::GenerateProbe(masm, flags, eax, ecx, ebx, edx);
1522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Cache miss: Jump to runtime.
1524402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateMiss(masm);
1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateNormal(MacroAssembler* masm) {
1529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1530402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : receiver
1531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
1532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss, probe, global;
1535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver isn't a smi.
1537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ test(eax, Immediate(kSmiTagMask));
1538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(zero, &miss, not_taken);
1539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver is a valid JS object.
1541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
1542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movzx_b(edx, FieldOperand(ebx, Map::kInstanceTypeOffset));
1543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(edx, FIRST_JS_OBJECT_TYPE);
1544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(less, &miss, not_taken);
1545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If this assert fails, we have to check upper bound too.
1547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
1548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for access to global object (unlikely).
1550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(edx, JS_GLOBAL_PROXY_TYPE);
1551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(equal, &global, not_taken);
1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for non-global object that requires access check.
15547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ test_b(FieldOperand(ebx, Map::kBitFieldOffset),
15557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            1 << Map::kIsAccessCheckNeeded);
1556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_zero, &miss, not_taken);
1557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Search the dictionary placing the result in eax.
1559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&probe);
1560402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateDictionaryLoad(masm,
1561402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                         &miss,
1562402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                         eax,
1563402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                         ecx,
1564402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                         edx,
1565402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                         edi,
1566402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                         ebx,
15677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                         edi,
1568402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                         CHECK_DICTIONARY);
1569402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(eax, edi);
1570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
1571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Global object access: Check access rights.
1573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&global);
1574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CheckAccessGlobalProxy(eax, edx, &miss);
1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(&probe);
1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Cache miss: Jump to runtime.
1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1579402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateMiss(masm);
1580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateMiss(MacroAssembler* masm) {
1584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1585402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : receiver
1586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
1587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
1588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(ebx);
1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(eax);  // receiver
1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ecx);  // name
1593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ebx);  // return address
1594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform tail call to the entry.
15966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss));
15976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallExternalReference(ref, 2, 1);
1598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// One byte opcode for test eax,0xXXXXXXXX.
1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const byte kTestEaxByte = 0xA9;
1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::ClearInlinedVersion(Address address) {
1606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reset the map check of the inlined inobject property load (if
1607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // present) to guarantee failure by holding an invalid map (the null
1608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // value).  The offset can be patched to anything.
1609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PatchInlinedLoad(address, Heap::null_value(), kMaxInt);
1610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid KeyedLoadIC::ClearInlinedVersion(Address address) {
1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Insert null as the map to check for to make sure the map check fails
1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sending control flow to the IC instead of the inlined version.
1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PatchInlinedLoad(address, Heap::null_value());
1617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid KeyedStoreIC::ClearInlinedVersion(Address address) {
1621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Insert null as the elements map to check for.  This will make
1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sure that the elements fast-case map check fails so that control
1623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // flows to the IC instead of the inlined version.
1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PatchInlinedStore(address, Heap::null_value());
1625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid KeyedStoreIC::RestoreInlinedVersion(Address address) {
1629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Restore the fast-case elements map check so that the inlined
1630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // version can be used again.
1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PatchInlinedStore(address, Heap::fixed_array_map());
1632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) {
1636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The address of the instruction following the call.
1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address test_instruction_address =
1638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      address + Assembler::kCallTargetAddressOffset;
1639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the instruction following the call is not a test eax, nothing
1640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // was inlined.
1641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (*test_instruction_address != kTestEaxByte) return false;
1642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address delta_address = test_instruction_address + 1;
1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The delta to the start of the map check instruction.
1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int delta = *reinterpret_cast<int*>(delta_address);
1646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The map address is the last 4 bytes of the 7-byte
1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // operand-immediate compare instruction, so we add 3 to get the
1649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // offset to the last 4 bytes.
1650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address map_address = test_instruction_address + delta + 3;
1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  *(reinterpret_cast<Object**>(map_address)) = map;
1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The offset is in the last 4 bytes of a six byte
1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // memory-to-register move instruction, so we add 2 to get the
1655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // offset to the last 4 bytes.
1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address offset_address =
1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      test_instruction_address + delta + kOffsetToLoadInstruction + 2;
1658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag;
1659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool PatchInlinedMapCheck(Address address, Object* map) {
1664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address test_instruction_address =
1665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      address + Assembler::kCallTargetAddressOffset;
1666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The keyed load has a fast inlined case if the IC call instruction
1667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is immediately followed by a test instruction.
1668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (*test_instruction_address != kTestEaxByte) return false;
1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fetch the offset from the test instruction to the map cmp
1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // instruction.  This offset is stored in the last 4 bytes of the 5
1672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // byte test instruction.
1673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address delta_address = test_instruction_address + 1;
1674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int delta = *reinterpret_cast<int*>(delta_address);
1675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute the map address.  The map address is in the last 4 bytes
1676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // of the 7-byte operand-immediate compare instruction, so we add 3
1677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to the offset to get the map address.
1678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address map_address = test_instruction_address + delta + 3;
1679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Patch the map check.
1680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  *(reinterpret_cast<Object**>(map_address)) = map;
1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
1682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool KeyedLoadIC::PatchInlinedLoad(Address address, Object* map) {
1686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return PatchInlinedMapCheck(address, map);
1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool KeyedStoreIC::PatchInlinedStore(Address address, Object* map) {
1691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return PatchInlinedMapCheck(address, map);
1692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Defined in ic.cc.
1696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadIC_Miss(Arguments args);
1697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
1700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1701402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
1702402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
1703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
1704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1706402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ pop(ebx);
1707402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(edx);  // receiver
1708402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(eax);  // name
1709402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(ebx);  // return address
1710402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1711402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Perform tail call to the entry.
17126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss));
17136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallExternalReference(ref, 2, 1);
1714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1717402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
1718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1719402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
1720402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
1721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
1722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(ebx);
1725402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(edx);  // receiver
1726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(eax);  // name
1727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ebx);  // return address
1728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform tail call to the entry.
17306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
1731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
1735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- eax    : value
1737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
17384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- edx    : receiver
1739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
1740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Code::Flags flags = Code::ComputeFlags(Code::STORE_IC,
1743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                         NOT_IN_LOOP,
1744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                         MONOMORPHIC);
1745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg);
1746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Cache miss: Jump to runtime.
17484515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  GenerateMiss(masm);
1749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17524515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid StoreIC::GenerateMiss(MacroAssembler* masm) {
1753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- eax    : value
1755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
17564515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- edx    : receiver
1757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
1758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(ebx);
17614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ push(edx);
1762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ecx);
1763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(eax);
1764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ebx);
1765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform tail call to the entry.
17676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_Miss));
17686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallExternalReference(ref, 3, 1);
17696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
17706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17726ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid StoreIC::GenerateArrayLength(MacroAssembler* masm) {
17736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
17746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- eax    : value
17756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ecx    : name
17766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- edx    : receiver
17776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- esp[0] : return address
17786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
17796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //
17806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // This accepts as a receiver anything JSObject::SetElementsLength accepts
17816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // (currently anything except for external and pixel arrays which means
17826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // anything with elements of FixedArray type.), but currently is restricted
17836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // to JSArray.
17846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Value must be a number, but only smis are accepted as the most common case.
17856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss;
17876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register receiver = edx;
17896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register value = eax;
17906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register scratch = ebx;
17916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the receiver isn't a smi.
17936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ test(receiver, Immediate(kSmiTagMask));
17946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ j(zero, &miss, not_taken);
17956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the object is a JS array.
17976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
17986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ j(not_equal, &miss, not_taken);
17996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that elements are FixedArray.
18016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(scratch, FieldOperand(receiver, JSArray::kElementsOffset));
18026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch);
18036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ j(not_equal, &miss, not_taken);
18046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that value is a smi.
18066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ test(value, Immediate(kSmiTagMask));
18076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ j(not_zero, &miss, not_taken);
18086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Prepare tail call to StoreIC_ArrayLength.
18106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ pop(scratch);
18116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(receiver);
18126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(value);
18136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(scratch);  // return address
18146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_ArrayLength));
18166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallExternalReference(ref, 2, 1);
18176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss);
18196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  GenerateMiss(masm);
1821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Defined in ic.cc.
1825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedStoreIC_Miss(Arguments args);
1826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1827402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) {
1828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- eax    : value
18306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ecx    : key
18316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- edx    : receiver
1832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
1833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
18356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ pop(ebx);
18366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(edx);
1837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ecx);
18386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(eax);
18396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(ebx);
1840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do tail-call to runtime routine.
18426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallRuntime(Runtime::kSetProperty, 3, 1);
1843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1846402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
1847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- eax    : value
18496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ecx    : key
18506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- edx    : receiver
1851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
1852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
18546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ pop(ebx);
18556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(edx);
1856402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(ecx);
18576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(eax);
18586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(ebx);
1859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do tail-call to runtime routine.
18616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss));
18626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallExternalReference(ref, 3, 1);
1863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __
1866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
1869f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1870f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_IA32
1871