13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_IA32)
31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "codegen.h"
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "ic-inl.h"
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "runtime.h"
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "stub-cache.h"
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Static IC stub generators.
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm)
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
478defd9ff6930b4e24729971a61cf7469daf119beSteve Blockstatic void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm,
488defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                            Register type,
498defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                            Label* global_object) {
508defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Register usage:
518defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //   type: holds the receiver instance type on entry.
528defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ cmp(type, JS_GLOBAL_OBJECT_TYPE);
53257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(equal, global_object);
548defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ cmp(type, JS_BUILTINS_OBJECT_TYPE);
55257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(equal, global_object);
568defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ cmp(type, JS_GLOBAL_PROXY_TYPE);
57257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(equal, global_object);
588defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
618defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Generated code falls through if the receiver is a regular non-global
628defd9ff6930b4e24729971a61cf7469daf119beSteve Block// JS object with slow properties and no interceptors.
638defd9ff6930b4e24729971a61cf7469daf119beSteve Blockstatic void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm,
648defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                                  Register receiver,
658defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                                  Register r0,
668defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                                  Register r1,
678defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                                  Label* miss) {
688defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Register usage:
698defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //   receiver: holds the receiver on entry and is unchanged.
708defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //   r0: used to hold receiver instance type.
718defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //       Holds the property dictionary on fall through.
728defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //   r1: used to hold receivers map.
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
748defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Check that the receiver isn't a smi.
753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver, miss);
768defd9ff6930b4e24729971a61cf7469daf119beSteve Block
778defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Check that the receiver is a valid JS object.
788defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ mov(r1, FieldOperand(receiver, HeapObject::kMapOffset));
798defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ movzx_b(r0, FieldOperand(r1, Map::kInstanceTypeOffset));
803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmp(r0, FIRST_SPEC_OBJECT_TYPE);
81257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(below, miss);
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
838defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // If this assert fails, we have to check upper bound too.
843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE);
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
868defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateGlobalInstanceTypeCheck(masm, r0, miss);
878defd9ff6930b4e24729971a61cf7469daf119beSteve Block
888defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Check for non-global object that requires access check.
898defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ test_b(FieldOperand(r1, Map::kBitFieldOffset),
908defd9ff6930b4e24729971a61cf7469daf119beSteve Block            (1 << Map::kIsAccessCheckNeeded) |
918defd9ff6930b4e24729971a61cf7469daf119beSteve Block            (1 << Map::kHasNamedInterceptor));
92257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_zero, miss);
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
94402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(r0, FieldOperand(receiver, JSObject::kPropertiesOffset));
95257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ CheckMap(r0, FACTORY->hash_table_map(), miss, DONT_DO_SMI_CHECK);
968defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
97e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
998defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Helper function used to load a property from a dictionary backing
1008defd9ff6930b4e24729971a61cf7469daf119beSteve Block// storage. This function may fail to load a property even though it is
1018defd9ff6930b4e24729971a61cf7469daf119beSteve Block// in the dictionary, so code at miss_label must always call a backup
1028defd9ff6930b4e24729971a61cf7469daf119beSteve Block// property load that is complete. This function is safe to call if
1038defd9ff6930b4e24729971a61cf7469daf119beSteve Block// name is not a symbol, and will jump to the miss_label in that
1048defd9ff6930b4e24729971a61cf7469daf119beSteve Block// case. The generated code assumes that the receiver has slow
1058defd9ff6930b4e24729971a61cf7469daf119beSteve Block// properties, is not a global object and does not have interceptors.
1068defd9ff6930b4e24729971a61cf7469daf119beSteve Blockstatic void GenerateDictionaryLoad(MacroAssembler* masm,
1078defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                   Label* miss_label,
1088defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                   Register elements,
1098defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                   Register name,
1108defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                   Register r0,
1118defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                   Register r1,
1128defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                   Register result) {
1138defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Register use:
1148defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //
1158defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // elements - holds the property dictionary on entry and is unchanged.
1168defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //
1178defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // name - holds the name of the property on entry and is unchanged.
1188defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //
1198defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Scratch registers:
1208defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //
1218defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // r0   - used for the index into the property dictionary
1228defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //
1238defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // r1   - used to hold the capacity of the property dictionary.
1248defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //
1258defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // result - holds the result on exit.
1268defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1278defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Label done;
1288defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1298defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Probe the dictionary.
130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  StringDictionaryLookupStub::GeneratePositiveLookup(masm,
131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                     miss_label,
132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                     &done,
133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                     elements,
134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                     name,
135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                     r0,
136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                     r1);
1378defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1388defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // If probing finds an entry in the dictionary, r0 contains the
1398defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // index into the dictionary. Check that the value is a normal
1408defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // property.
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&done);
1428defd9ff6930b4e24729971a61cf7469daf119beSteve Block  const int kElementsStartOffset =
1438defd9ff6930b4e24729971a61cf7469daf119beSteve Block      StringDictionary::kHeaderSize +
1448defd9ff6930b4e24729971a61cf7469daf119beSteve Block      StringDictionary::kElementsStartIndex * kPointerSize;
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
1468defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag),
147589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize));
148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_zero, miss_label);
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the value at the masked, scaled index.
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kValueOffset = kElementsStartOffset + kPointerSize;
1528defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ mov(result, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag));
1538defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
1548defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1558defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1568defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Helper function used to store a property to a dictionary backing
1578defd9ff6930b4e24729971a61cf7469daf119beSteve Block// storage. This function may fail to store a property eventhough it
1588defd9ff6930b4e24729971a61cf7469daf119beSteve Block// is in the dictionary, so code at miss_label must always call a
1598defd9ff6930b4e24729971a61cf7469daf119beSteve Block// backup property store that is complete. This function is safe to
1608defd9ff6930b4e24729971a61cf7469daf119beSteve Block// call if name is not a symbol, and will jump to the miss_label in
1618defd9ff6930b4e24729971a61cf7469daf119beSteve Block// that case. The generated code assumes that the receiver has slow
1628defd9ff6930b4e24729971a61cf7469daf119beSteve Block// properties, is not a global object and does not have interceptors.
1638defd9ff6930b4e24729971a61cf7469daf119beSteve Blockstatic void GenerateDictionaryStore(MacroAssembler* masm,
1648defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                    Label* miss_label,
1658defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                    Register elements,
1668defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                    Register name,
1678defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                    Register value,
1688defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                    Register r0,
1698defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                    Register r1) {
1708defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Register use:
1718defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //
1728defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // elements - holds the property dictionary on entry and is clobbered.
1738defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //
1748defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // name - holds the name of the property on entry and is unchanged.
1758defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //
1768defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // value - holds the value to store and is unchanged.
1778defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //
1788defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // r0 - used for index into the property dictionary and is clobbered.
1798defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //
1808defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // r1 - used to hold the capacity of the property dictionary and is clobbered.
1818defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Label done;
1828defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1838defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1848defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Probe the dictionary.
185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  StringDictionaryLookupStub::GeneratePositiveLookup(masm,
186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                     miss_label,
187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                     &done,
188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                     elements,
189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                     name,
190257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                     r0,
191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                     r1);
1928defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1938defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // If probing finds an entry in the dictionary, r0 contains the
1948defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // index into the dictionary. Check that the value is a normal
1958defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // property that is not read only.
1968defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ bind(&done);
1978defd9ff6930b4e24729971a61cf7469daf119beSteve Block  const int kElementsStartOffset =
1988defd9ff6930b4e24729971a61cf7469daf119beSteve Block      StringDictionary::kHeaderSize +
1998defd9ff6930b4e24729971a61cf7469daf119beSteve Block      StringDictionary::kElementsStartIndex * kPointerSize;
2008defd9ff6930b4e24729971a61cf7469daf119beSteve Block  const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
201589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  const int kTypeAndReadOnlyMask =
202589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      (PropertyDetails::TypeField::kMask |
203589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch       PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize;
2048defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag),
2058defd9ff6930b4e24729971a61cf7469daf119beSteve Block          Immediate(kTypeAndReadOnlyMask));
206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_zero, miss_label);
2078defd9ff6930b4e24729971a61cf7469daf119beSteve Block
2088defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Store the value at the masked, scaled index.
2098defd9ff6930b4e24729971a61cf7469daf119beSteve Block  const int kValueOffset = kElementsStartOffset + kPointerSize;
2108defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ lea(r0, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag));
2118defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ mov(Operand(r0, 0), value);
2128defd9ff6930b4e24729971a61cf7469daf119beSteve Block
2138defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Update write barrier. Make sure not to clobber the value.
2148defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ mov(r1, value);
2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ RecordWrite(elements, r0, r1, kDontSaveFPRegs);
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateArrayLength(MacroAssembler* masm) {
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
221402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : receiver
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StubCompiler::GenerateLoadArrayLength(masm, eax, edx, &miss);
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid LoadIC::GenerateStringLength(MacroAssembler* masm,
2341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                  bool support_wrappers) {
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
236402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : receiver
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  StubCompiler::GenerateLoadStringLength(masm, eax, edx, ebx, &miss,
2431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                         support_wrappers);
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
251402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : receiver
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label miss;
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StubCompiler::GenerateLoadFunctionPrototype(masm, eax, edx, ebx, &miss);
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Checks the receiver for special cases (value type, slow case bits).
2647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Falls through for regular JS object.
2657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
2667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                           Register receiver,
2679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                           Register map,
2688defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                           int interceptor_bit,
2697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                           Label* slow) {
2707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Register use:
2717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //   receiver - holds the receiver and is unchanged.
2727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Scratch registers:
2739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  //   map - used to hold the map of the receiver.
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object isn't a smi.
2763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver, slow);
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the map of the receiver.
2799dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ mov(map, FieldOperand(receiver, HeapObject::kMapOffset));
280d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
281d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Check bit field.
2829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ test_b(FieldOperand(map, Map::kBitFieldOffset),
2838defd9ff6930b4e24729971a61cf7469daf119beSteve Block            (1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit));
284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_zero, slow);
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object is some kind of JS object EXCEPT JS Value type.
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // In the case that the object is a value-wrapper object,
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // we enter the runtime system to make sure that indexing
2887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // into string objects works as intended.
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
2907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2919dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ CmpInstanceType(map, JS_OBJECT_TYPE);
292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(below, slow);
2937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Loads an indexed element from a fast case array.
297756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick// If not_fast_array is NULL, doesn't perform the elements map check.
2987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void GenerateFastArrayLoad(MacroAssembler* masm,
2997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  Register receiver,
3007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  Register key,
3017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  Register scratch,
3027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  Register result,
3037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  Label* not_fast_array,
3047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                  Label* out_of_range) {
3057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Register use:
3067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //   receiver - holds the receiver and is unchanged.
3077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //   key - holds the key and is unchanged (must be a smi).
3087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Scratch registers:
3097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //   scratch - used to hold elements of the receiver and the loaded value.
3107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //   result - holds the result on exit if the load succeeds and
3117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //            we fall through.
3127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(scratch, FieldOperand(receiver, JSObject::kElementsOffset));
314756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (not_fast_array != NULL) {
315756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Check that the object is in fast mode and writable.
316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ CheckMap(scratch,
317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                FACTORY->fixed_array_map(),
318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                not_fast_array,
319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                DONT_DO_SMI_CHECK);
320756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  } else {
321756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ AssertFastElements(scratch);
322756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the key (index) is within bounds.
3247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ cmp(key, FieldOperand(scratch, FixedArray::kLengthOffset));
3257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ j(above_equal, out_of_range);
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fast case: Do the load.
32769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0));
3287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(scratch, FieldOperand(scratch, key, times_2, FixedArray::kHeaderSize));
3293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(scratch, Immediate(FACTORY->the_hole_value()));
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // In case the loaded value is the_hole we have to consult GetProperty
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to ensure the prototype chain is searched.
3327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ j(equal, out_of_range);
3337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (!result.is(scratch)) {
3347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ mov(result, scratch);
3357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
3367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
3377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Checks whether a key is an array index string or a symbol string.
3409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen// Falls through if the key is a symbol.
3417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void GenerateKeyStringCheck(MacroAssembler* masm,
3427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   Register key,
3437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   Register map,
3447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   Register hash,
3457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   Label* index_string,
3467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                   Label* not_symbol) {
3477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Register use:
3487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //   key - holds the key and is unchanged. Assumed to be non-smi.
3497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Scratch registers:
3507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //   map - used to hold the map of the key.
3517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //   hash - used to hold the hash of the key.
3527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ CmpObjectType(key, FIRST_NONSTRING_TYPE, map);
3537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ j(above_equal, not_symbol);
3547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Is the string an array index, with cached numeric value?
3567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(hash, FieldOperand(key, String::kHashFieldOffset));
3577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ test(hash, Immediate(String::kContainsCachedArrayIndexMask));
358257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(zero, index_string);
3597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Is the string a symbol?
36169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSymbolTag != 0);
3627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsSymbolMask);
363257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(zero, not_symbol);
3647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
3657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochstatic Operand GenerateMappedArgumentsLookup(MacroAssembler* masm,
3683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                             Register object,
3693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                             Register key,
3703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                             Register scratch1,
3713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                             Register scratch2,
3723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                             Label* unmapped_case,
3733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                             Label* slow_case) {
3743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Heap* heap = masm->isolate()->heap();
3753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Factory* factory = masm->isolate()->factory();
3763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the receiver is a JSObject. Because of the elements
3783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // map check later, we do not need to check for interceptors or
3793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // whether it requires access checks.
3803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(object, slow_case);
3813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the object is some kind of JSObject.
3823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CmpObjectType(object, FIRST_JS_RECEIVER_TYPE, scratch1);
3833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(below, slow_case);
3843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is a positive smi.
3867a930e02c0b52d70d022ed255db551895dfe1157Ben Murdoch  __ test(key, Immediate(0x80000001));
3873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(not_zero, slow_case);
3883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Load the elements into scratch1 and check its map.
3903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Map> arguments_map(heap->non_strict_arguments_elements_map());
3913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(scratch1, FieldOperand(object, JSObject::kElementsOffset));
3923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CheckMap(scratch1, arguments_map, slow_case, DONT_DO_SMI_CHECK);
3933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check if element is in the range of mapped arguments. If not, jump
3953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // to the unmapped lookup with the parameter map in scratch1.
3963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(scratch2, FieldOperand(scratch1, FixedArray::kLengthOffset));
3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sub(scratch2, Immediate(Smi::FromInt(2)));
3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(key, scratch2);
3997a930e02c0b52d70d022ed255db551895dfe1157Ben Murdoch  __ j(above_equal, unmapped_case);
4003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Load element index and check whether it is the hole.
4023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int kHeaderSize = FixedArray::kHeaderSize + 2 * kPointerSize;
4033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(scratch2, FieldOperand(scratch1,
4043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                key,
4053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                times_half_pointer_size,
4063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                kHeaderSize));
4073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmp(scratch2, factory->the_hole_value());
4083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(equal, unmapped_case);
4093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Load value from context and return it. We can reuse scratch1 because
4113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // we do not jump to the unmapped lookup (which requires the parameter
4123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // map in scratch1).
4133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int kContextOffset = FixedArray::kHeaderSize;
4143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(scratch1, FieldOperand(scratch1, kContextOffset));
4153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return FieldOperand(scratch1,
4163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                      scratch2,
4173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                      times_half_pointer_size,
4183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                      Context::kHeaderSize);
4193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
4203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochstatic Operand GenerateUnmappedArgumentsLookup(MacroAssembler* masm,
4233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                               Register key,
4243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                               Register parameter_map,
4253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                               Register scratch,
4263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                               Label* slow_case) {
4273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Element is in arguments backing store, which is referenced by the
4283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // second element of the parameter_map.
4293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize;
4303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register backing_store = parameter_map;
4313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(backing_store, FieldOperand(parameter_map, kBackingStoreOffset));
4323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Map> fixed_array_map(masm->isolate()->heap()->fixed_array_map());
4333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CheckMap(backing_store, fixed_array_map, slow_case, DONT_DO_SMI_CHECK);
4343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(scratch, FieldOperand(backing_store, FixedArray::kLengthOffset));
4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(key, scratch);
4363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(greater_equal, slow_case);
4373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return FieldOperand(backing_store,
4383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                      key,
4393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                      times_half_pointer_size,
4403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                      FixedArray::kHeaderSize);
4413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
4423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
4457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // ----------- S t a t e -------------
4467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- eax    : key
4477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- edx    : receiver
4487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[0] : return address
4497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // -----------------------------------
450bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label slow, check_string, index_smi, index_string, property_array_property;
45144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label probe_dictionary, check_number_dictionary;
4527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
4537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Check that the key is a smi.
4543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(eax, &check_string);
4557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_smi);
4567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Now the key is known to be a smi. This place is also jumped to from
4577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // where a numeric string is converted to a smi.
4587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
4598defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateKeyedLoadReceiverCheck(
4608defd9ff6930b4e24729971a61cf7469daf119beSteve Block      masm, edx, ecx, Map::kHasIndexedInterceptor, &slow);
4618defd9ff6930b4e24729971a61cf7469daf119beSteve Block
4623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check the receiver's map to see if it has fast elements.
4633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CheckFastElements(ecx, &check_number_dictionary);
464756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
4657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateFastArrayLoad(masm,
4667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                        edx,
4677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                        eax,
4687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                        ecx,
4697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                        eax,
470756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                        NULL,
4717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                        &slow);
47244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate = masm->isolate();
47344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate->counters();
47444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_generic_smi(), 1);
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
4766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&check_number_dictionary);
47744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(ebx, eax);
47844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ SmiUntag(ebx);
47944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
48044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check whether the elements is a number dictionary.
4826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // edx: receiver
4836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ebx: untagged index
4846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // eax: key
4856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ecx: elements
486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ CheckMap(ecx,
487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              isolate->factory()->hash_table_map(),
488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              &slow,
489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              DONT_DO_SMI_CHECK);
4906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label slow_pop_receiver;
4916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Push receiver on the stack to free up a register for the dictionary
4926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // probing.
4936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(edx);
4943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ LoadFromNumberDictionary(&slow_pop_receiver,
4953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              ecx,
4963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              eax,
4973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              ebx,
4983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              edx,
4993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              edi,
5003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                              eax);
5016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Pop receiver before returning.
5026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ pop(edx);
5036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ret(0);
5046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&slow_pop_receiver);
5066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Pop the receiver from the stack and jump to runtime.
5076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ pop(edx);
5086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&slow);
510402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Slow case: jump to runtime.
511402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // edx: receiver
512402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // eax: key
51344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_generic_slow(), 1);
514402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateRuntimeGetProperty(masm);
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&check_string);
5177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateKeyStringCheck(masm, eax, ecx, ebx, &index_string, &slow);
518e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5198defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateKeyedLoadReceiverCheck(
5208defd9ff6930b4e24729971a61cf7469daf119beSteve Block      masm, edx, ecx, Map::kHasNamedInterceptor, &slow);
5218defd9ff6930b4e24729971a61cf7469daf119beSteve Block
522e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // If the receiver is a fast-case object, check the keyed lookup
523402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // cache. Otherwise probe the dictionary.
524402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset));
525e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
52644f0eee88ff00398ff7f715fab053374d808c90dSteve Block         Immediate(isolate->factory()->hash_table_map()));
527e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, &probe_dictionary);
528e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
529e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Load the map of the receiver, compute the keyed lookup cache hash
530e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // based on 32 bits of the map pointer and the string hash.
531402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
532402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(ecx, ebx);
533402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ shr(ecx, KeyedLookupCache::kMapHashShift);
534402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(edi, FieldOperand(eax, String::kHashFieldOffset));
535402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ shr(edi, String::kHashShift);
5363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ xor_(ecx, edi);
5373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ and_(ecx, KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask);
538e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
539e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Load the key (consisting of map and symbol) from the cache and
540e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // check for match.
5413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label load_in_object_property;
5423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket;
5433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label hit_on_nth_entry[kEntriesPerBucket];
54444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference cache_keys =
54544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::keyed_lookup_cache_keys(masm->isolate());
5463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < kEntriesPerBucket - 1; i++) {
5483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label try_next_entry;
5493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(edi, ecx);
5503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ shl(edi, kPointerSizeLog2 + 1);
5513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (i != 0) {
5523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ add(edi, Immediate(kPointerSize * i * 2));
5533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys));
5553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &try_next_entry);
5563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(edi, Immediate(kPointerSize));
5573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(eax, Operand::StaticArray(edi, times_1, cache_keys));
5583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(equal, &hit_on_nth_entry[i]);
5593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&try_next_entry);
5603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lea(edi, Operand(ecx, 1));
563e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ shl(edi, kPointerSizeLog2 + 1);
5643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(edi, Immediate(kPointerSize * (kEntriesPerBucket - 1) * 2));
565e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys));
566e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(not_equal, &slow);
5673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(edi, Immediate(kPointerSize));
568402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ cmp(eax, Operand::StaticArray(edi, times_1, cache_keys));
569e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(not_equal, &slow);
570e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
571bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Get field offset.
572402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // edx     : receiver
573402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // ebx     : receiver's map
574402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // eax     : key
575402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // ecx     : lookup cache index
57644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference cache_field_offsets =
57744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate());
5783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Hit on nth entry.
5803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = kEntriesPerBucket - 1; i >= 0; i--) {
5813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&hit_on_nth_entry[i]);
5823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (i != 0) {
5833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ add(ecx, Immediate(i));
5843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(edi,
5863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Operand::StaticArray(ecx, times_pointer_size, cache_field_offsets));
5873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movzx_b(ecx, FieldOperand(ebx, Map::kInObjectPropertiesOffset));
5883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sub(edi, ecx);
5893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(above_equal, &property_array_property);
5903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (i != 0) {
5913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(&load_in_object_property);
5923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
594e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
595e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Load in-object property.
5963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&load_in_object_property);
597402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset));
5983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(ecx, edi);
599402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(eax, FieldOperand(edx, ecx, times_pointer_size, 0));
60044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1);
601e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ ret(0);
602e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
603bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Load property array property.
604bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&property_array_property);
605bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ mov(eax, FieldOperand(edx, JSObject::kPropertiesOffset));
606bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ mov(eax, FieldOperand(eax, edi, times_pointer_size,
607bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                           FixedArray::kHeaderSize));
60844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1);
609bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ ret(0);
610bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
611e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Do a quick inline probe of the receiver's dictionary, if it
612e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // exists.
613e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ bind(&probe_dictionary);
6148defd9ff6930b4e24729971a61cf7469daf119beSteve Block
6158defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ mov(ecx, FieldOperand(edx, JSObject::kMapOffset));
6168defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
6178defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateGlobalInstanceTypeCheck(masm, ecx, &slow);
6188defd9ff6930b4e24729971a61cf7469daf119beSteve Block
6198defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateDictionaryLoad(masm, &slow, ebx, eax, ecx, edi, eax);
62044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_generic_symbol(), 1);
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
622e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&index_string);
62480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ IndexFromHash(ebx, eax);
6259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Now jump to the place where smi keys are handled.
6269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ jmp(&index_smi);
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
630e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid KeyedLoadIC::GenerateString(MacroAssembler* masm) {
631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // ----------- S t a t e -------------
6326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- eax    : key (index)
633402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
634e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[0] : return address
635e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // -----------------------------------
6366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss;
6376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register receiver = edx;
6396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register index = eax;
6403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = ecx;
6417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = eax;
6427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
6437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharAtGenerator char_at_generator(receiver,
6447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                          index,
6453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          scratch,
6467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                          result,
6477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                          &miss,  // When not a string.
6487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                          &miss,  // When not a number.
6490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                          &miss,  // When index out of range.
6507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                          STRING_INDEX_IS_ARRAY_INDEX);
6517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  char_at_generator.GenerateFast(masm);
6527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ ret(0);
6537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StubRuntimeCallHelper call_helper;
6557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  char_at_generator.GenerateSlow(masm, call_helper);
656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
657e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ bind(&miss);
658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateMiss(masm, false);
659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
661e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
662402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
663402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // ----------- S t a t e -------------
664402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
665402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
666402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- esp[0] : return address
667402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // -----------------------------------
668402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Label slow;
669402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
670402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Check that the receiver isn't a smi.
6713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(edx, &slow);
672402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
673f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Check that the key is an array index, that is Uint32.
674f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ test(eax, Immediate(kSmiTagMask | kSmiSignMask));
675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_zero, &slow);
676402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
677402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Get the map of the receiver.
678402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
679402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
680402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Check that it has indexed interceptor and access checks
681402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // are not enabled for this object.
682402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ movzx_b(ecx, FieldOperand(ecx, Map::kBitFieldOffset));
6833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ and_(ecx, Immediate(kSlowCaseBitFieldMask));
6843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(ecx, Immediate(1 << Map::kHasIndexedInterceptor));
685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_zero, &slow);
686402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
687402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Everything is fine, call runtime.
688402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ pop(ecx);
689402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(edx);  // receiver
690402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(eax);  // key
691402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(ecx);  // return address
692402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
693402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Perform tail call to the entry.
69444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference ref =
69544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor),
69644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        masm->isolate());
6976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallExternalReference(ref, 2, 1);
698402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
699402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ bind(&slow);
700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateMiss(masm, false);
7013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
7023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadIC::GenerateNonStrictArguments(MacroAssembler* masm) {
7053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ----------- S t a t e -------------
7063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- eax    : key
7073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- edx    : receiver
7083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- esp[0] : return address
7093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
7103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label slow, notin;
7113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Factory* factory = masm->isolate()->factory();
7123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Operand mapped_location =
7133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      GenerateMappedArgumentsLookup(masm, edx, eax, ebx, ecx, &notin, &slow);
7143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(eax, mapped_location);
7153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Ret();
7163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&notin);
7173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // The unmapped lookup expects that the parameter map is in ebx.
7183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Operand unmapped_location =
7193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      GenerateUnmappedArgumentsLookup(masm, eax, ebx, ecx, &slow);
7203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmp(unmapped_location, factory->the_hole_value());
7213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(equal, &slow);
7223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(eax, unmapped_location);
7233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Ret();
7243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&slow);
7253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  GenerateMiss(masm, false);
7263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
7273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedStoreIC::GenerateNonStrictArguments(MacroAssembler* masm) {
7303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ----------- S t a t e -------------
7313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- eax    : value
7323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- ecx    : key
7333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- edx    : receiver
7343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- esp[0] : return address
7353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
7363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label slow, notin;
7373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Operand mapped_location =
7383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      GenerateMappedArgumentsLookup(masm, edx, ecx, ebx, edi, &notin, &slow);
7393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(mapped_location, eax);
7403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ lea(ecx, mapped_location);
7413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(edx, eax);
7423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ RecordWrite(ebx, ecx, edx, kDontSaveFPRegs);
7433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Ret();
7443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&notin);
7453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // The unmapped lookup expects that the parameter map is in ebx.
7463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Operand unmapped_location =
7473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      GenerateUnmappedArgumentsLookup(masm, ecx, ebx, edi, &slow);
7483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(unmapped_location, eax);
7493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ lea(edi, unmapped_location);
7503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(edx, eax);
7513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ RecordWrite(ebx, edi, edx, kDontSaveFPRegs);
7523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Ret();
7533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&slow);
7543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  GenerateMiss(masm, false);
7553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
7563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
758e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
759e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   StrictModeFlag strict_mode) {
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- eax    : value
7626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ecx    : key
7636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- edx    : receiver
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
7663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label slow, fast_object_with_map_check, fast_object_without_map_check;
7673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label fast_double_with_map_check, fast_double_without_map_check;
7683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label check_if_double_array, array, extra, transition_smi_elements;
7693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label finish_object_store, non_double_value, transition_double_elements;
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object isn't a smi.
7723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(edx, &slow);
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the map from the receiver.
7746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver does not require access checks.  We need
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to do this because this generic stub does not perform map checks.
7777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ test_b(FieldOperand(edi, Map::kBitFieldOffset),
7787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            1 << Map::kIsAccessCheckNeeded);
779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_zero, &slow);
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the key is a smi.
7813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(ecx, &slow);
7826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ CmpInstanceType(edi, JS_ARRAY_TYPE);
783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(equal, &array);
7843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the object is some kind of JSObject.
7853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE);
786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(below, &slow);
787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Object case: Check key against length in the elements array.
789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // eax: value
790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // edx: JSObject
7916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ecx: key (a smi)
7923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // edi: receiver map
7933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
7943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check array bounds. Both the key and the length of FixedArray are smis.
7953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(ecx, FieldOperand(ebx, FixedArray::kLengthOffset));
7963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(below, &fast_object_with_map_check);
797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Slow case: call runtime.
799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&slow);
800e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  GenerateRuntimeSetProperty(masm, strict_mode);
801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Extra capacity case: Check if there is extra capacity to
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // perform the store and update the length. Used for adding one
804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // element to the array by writing to array[array.length].
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&extra);
806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // eax: value
8076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // edx: receiver, a JSArray
8086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ecx: key, a smi.
8093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ebx: receiver->elements, a FixedArray
8103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // edi: receiver map
8116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // flags: compare (ecx, edx.length())
812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // do not leave holes in the array:
813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &slow);
8143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(ecx, FieldOperand(ebx, FixedArray::kLengthOffset));
815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(above_equal, &slow);
8163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(edi, FieldOperand(ebx, HeapObject::kMapOffset));
8173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(edi, masm->isolate()->factory()->fixed_array_map());
8183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_equal, &check_if_double_array);
8193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Add 1 to receiver->length, and go to common element store code for Objects.
8203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(FieldOperand(edx, JSArray::kLengthOffset),
8213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         Immediate(Smi::FromInt(1)));
8223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&fast_object_without_map_check);
8233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&check_if_double_array);
8253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(edi, masm->isolate()->factory()->fixed_double_array_map());
8263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_equal, &slow);
8273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Add 1 to receiver->length, and go to common element store code for doubles.
8286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ add(FieldOperand(edx, JSArray::kLengthOffset),
8297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch         Immediate(Smi::FromInt(1)));
8303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&fast_double_without_map_check);
831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Array case: Get the length and the elements array from the JS
833756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // array. Check that the array is in fast mode (and writable); if it
834756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // is the length is always a smi.
835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&array);
836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // eax: value
8376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // edx: receiver, a JSArray
8386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ecx: key, a smi.
8393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // edi: receiver map
8403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check the key against the length in the array and fall through to the
8433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // common store code.
8446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset));  // Compare smis.
845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(above_equal, &extra);
846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Fast case: Do the store, could either Object or double.
8483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&fast_object_with_map_check);
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // eax: value
8506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ecx: key (a smi)
8516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // edx: receiver
8523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ebx: FixedArray receiver->elements
8533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // edi: receiver map
8543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(edi, FieldOperand(ebx, HeapObject::kMapOffset));
8553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(edi, masm->isolate()->factory()->fixed_array_map());
8563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_equal, &fast_double_with_map_check);
8573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&fast_object_without_map_check);
8583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Smi stores don't require further checks.
8593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label non_smi_value;
8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfNotSmi(eax, &non_smi_value);
8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // It's irrelevant whether array is smi-only or not when writing a smi.
8623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(CodeGenerator::FixedArrayElementOperand(ebx, ecx), eax);
8633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ret(0);
8643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&non_smi_value);
8663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Escape to elements kind transition case.
8673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
8683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckFastObjectElements(edi, &transition_smi_elements);
8693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Fast elements array, store the value to the elements backing store.
8713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&finish_object_store);
8723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(CodeGenerator::FixedArrayElementOperand(ebx, ecx), eax);
873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update write barrier for the elements array address.
8743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(edx, eax);  // Preserve the value which is returned.
8753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ RecordWriteArray(
8763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ebx, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
8773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ret(0);
8783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&fast_double_with_map_check);
8803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for fast double array case. If this fails, call through to the
8813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // runtime.
8823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(edi, masm->isolate()->factory()->fixed_double_array_map());
8833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_equal, &slow);
8843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&fast_double_without_map_check);
8853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the value is a number, store it as a double in the FastDoubleElements
8863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // array.
8873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ StoreNumberToDoubleElements(eax, ebx, ecx, edx, xmm0,
8883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 &transition_double_elements, false);
889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
8903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&transition_smi_elements);
8923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
8933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Transition the array appropriately depending on the value type.
8953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(eax,
8963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              masm->isolate()->factory()->heap_number_map(),
8973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              &non_double_value,
8983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              DONT_DO_SMI_CHECK);
8993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Value is a double. Transition FAST_SMI_ONLY_ELEMENTS ->
9013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // FAST_DOUBLE_ELEMENTS and complete the store.
9023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS,
9033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         FAST_DOUBLE_ELEMENTS,
9043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         ebx,
9053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         edi,
9063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         &slow);
9073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ElementsTransitionGenerator::GenerateSmiOnlyToDouble(masm, &slow);
9083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
9093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&fast_double_without_map_check);
9103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&non_double_value);
9123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Value is not a double, FAST_SMI_ONLY_ELEMENTS -> FAST_ELEMENTS
9133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS,
9143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         FAST_ELEMENTS,
9153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         ebx,
9163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         edi,
9173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         &slow);
9183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ElementsTransitionGenerator::GenerateSmiOnlyToObject(masm);
9193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
9203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&finish_object_store);
9213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&transition_double_elements);
9233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a
9243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and
9253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS
9263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
9273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS,
9283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         FAST_ELEMENTS,
9293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         ebx,
9303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         edi,
9313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         &slow);
9323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ElementsTransitionGenerator::GenerateDoubleToObject(masm, &slow);
9333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
9343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&finish_object_store);
935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// The generated code does not accept smi keys.
9397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// The generated code falls through if both probes miss.
9403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallICBase::GenerateMonomorphicCacheProbe(MacroAssembler* masm,
9413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               int argc,
9423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               Code::Kind kind,
9433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               Code::ExtraICState extra_state) {
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
945e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ecx                 : name
9467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- edx                 : receiver
947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
9489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  Label number, non_number, non_string, boolean, probe, miss;
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Probe the stub cache.
951b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Code::Flags flags = Code::ComputeFlags(kind,
952b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                         MONOMORPHIC,
9533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         extra_state,
954b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                         NORMAL,
955b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                         argc);
9563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Isolate* isolate = masm->isolate();
9573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  isolate->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx, eax);
958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the stub cache probing failed, the receiver might be a value.
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // For value objects, we use the map of the prototype objects for
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the corresponding JSValue for the cache and that is what we need
962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to probe.
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for number.
9653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(edx, &number);
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ebx);
967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &non_number);
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&number);
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StubCompiler::GenerateLoadGlobalFunctionPrototype(
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      masm, Context::NUMBER_FUNCTION_INDEX, edx);
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(&probe);
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for string.
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&non_number);
9757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ CmpInstanceType(ebx, FIRST_NONSTRING_TYPE);
976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(above_equal, &non_string);
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StubCompiler::GenerateLoadGlobalFunctionPrototype(
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      masm, Context::STRING_FUNCTION_INDEX, edx);
979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(&probe);
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for boolean.
982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&non_string);
9833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(edx, isolate->factory()->true_value());
984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(equal, &boolean);
9853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(edx, isolate->factory()->false_value());
986257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&boolean);
988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StubCompiler::GenerateLoadGlobalFunctionPrototype(
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      masm, Context::BOOLEAN_FUNCTION_INDEX, edx);
990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Probe the stub cache for the value object.
992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&probe);
9933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  isolate->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx, no_reg);
9949dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ bind(&miss);
995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9988defd9ff6930b4e24729971a61cf7469daf119beSteve Blockstatic void GenerateFunctionTailCall(MacroAssembler* masm,
9998defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                     int argc,
10008defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                     Label* miss) {
1001e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // ----------- S t a t e -------------
1002e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ecx                 : name
10038defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //  -- edi                 : function
1004e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[0]              : return address
1005e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
1006e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ...
1007e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc + 1) * 4] : receiver
1008e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // -----------------------------------
1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1010e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Check that the result is not a smi.
10113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(edi, miss);
1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1013e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Check that the value is a JavaScript function, fetching its map into eax.
1014e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax);
1015257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, miss);
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the function.
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount actual(argc);
1019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(edi, actual, JUMP_FUNCTION,
1020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), CALL_AS_METHOD);
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen// The generated code falls through if the call should be handled by runtime.
10253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallICBase::GenerateNormal(MacroAssembler* masm, int argc) {
1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1027e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ecx                 : name
1028e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[0]              : return address
1029e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
1030e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ...
1031e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc + 1) * 4] : receiver
1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
10338defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Label miss;
1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver of the function from the stack; 1 ~ return address.
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10388defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateStringDictionaryReceiverCheck(masm, edx, eax, ebx, &miss);
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10408defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // eax: elements
10418defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Search the dictionary placing the result in edi.
10428defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateDictionaryLoad(masm, &miss, eax, ecx, edi, ebx, edi);
10438defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateFunctionTailCall(masm, argc, &miss);
10449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
10459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ bind(&miss);
1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallICBase::GenerateMiss(MacroAssembler* masm,
10503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              int argc,
10513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              IC::UtilityId id,
10523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Code::ExtraICState extra_state) {
1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1054e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ecx                 : name
1055e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[0]              : return address
1056e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
1057e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ...
1058e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- esp[(argc + 1) * 4] : receiver
1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
106144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm->isolate()->counters();
10628defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (id == IC::kCallIC_Miss) {
106344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ IncrementCounter(counters->call_miss(), 1);
10648defd9ff6930b4e24729971a61cf7469daf119beSteve Block  } else {
106544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ IncrementCounter(counters->keyed_call_miss(), 1);
10668defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
10678defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver of the function from the stack; 1 ~ return address.
1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
10723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Push the receiver and the name of the function.
10753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(edx);
10763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(ecx);
1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Call the entry.
10793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CEntryStub stub(1);
10803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(eax, Immediate(2));
10813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(ebx, Immediate(ExternalReference(IC_Utility(id), masm->isolate())));
10823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallStub(&stub);
1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Move result to edi and exit the internal frame.
10853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(edi, eax);
10863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if the receiver is a global object of some sort.
10898defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // This can happen only for regular CallIC but not KeyedCallIC.
10908defd9ff6930b4e24729971a61cf7469daf119beSteve Block  if (id == IC::kCallIC_Miss) {
10918defd9ff6930b4e24729971a61cf7469daf119beSteve Block    Label invoke, global;
10928defd9ff6930b4e24729971a61cf7469daf119beSteve Block    __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));  // receiver
10933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(edx, &invoke, Label::kNear);
10948defd9ff6930b4e24729971a61cf7469daf119beSteve Block    __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
10958defd9ff6930b4e24729971a61cf7469daf119beSteve Block    __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
10968defd9ff6930b4e24729971a61cf7469daf119beSteve Block    __ cmp(ebx, JS_GLOBAL_OBJECT_TYPE);
1097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(equal, &global, Label::kNear);
10988defd9ff6930b4e24729971a61cf7469daf119beSteve Block    __ cmp(ebx, JS_BUILTINS_OBJECT_TYPE);
1099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(not_equal, &invoke, Label::kNear);
11008defd9ff6930b4e24729971a61cf7469daf119beSteve Block
11018defd9ff6930b4e24729971a61cf7469daf119beSteve Block    // Patch the receiver on the stack.
11028defd9ff6930b4e24729971a61cf7469daf119beSteve Block    __ bind(&global);
11038defd9ff6930b4e24729971a61cf7469daf119beSteve Block    __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
11048defd9ff6930b4e24729971a61cf7469daf119beSteve Block    __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
11058defd9ff6930b4e24729971a61cf7469daf119beSteve Block    __ bind(&invoke);
11068defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the function.
11093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state)
1110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
1111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount actual(argc);
1113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(edi,
1114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    actual,
1115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    JUMP_FUNCTION,
1116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(),
1117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    call_kind);
1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid CallIC::GenerateMegamorphic(MacroAssembler* masm,
1122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 int argc,
11233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Code::ExtraICState extra_state) {
11247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // ----------- S t a t e -------------
11257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- ecx                 : name
11267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[0]              : return address
11277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
11287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- ...
11297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[(argc + 1) * 4] : receiver
11307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // -----------------------------------
11317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Get the receiver of the function from the stack; 1 ~ return address.
11337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
11343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallICBase::GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC,
11353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            extra_state);
11369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
11373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMiss(masm, argc, extra_state);
11387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
11397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
11427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // ----------- S t a t e -------------
11437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- ecx                 : name
11447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[0]              : return address
11457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
11467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- ...
11477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- esp[(argc + 1) * 4] : receiver
11487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // -----------------------------------
11497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Get the receiver of the function from the stack; 1 ~ return address.
11517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
11527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label do_call, slow_call, slow_load, slow_reload_receiver;
11547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label check_number_dictionary, check_string, lookup_monomorphic_cache;
11557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Label index_smi, index_string;
11567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Check that the key is a smi.
11583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(ecx, &check_string);
11597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_smi);
11617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Now the key is known to be a smi. This place is also jumped to from
11627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // where a numeric string is converted to a smi.
11637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11648defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateKeyedLoadReceiverCheck(
11658defd9ff6930b4e24729971a61cf7469daf119beSteve Block      masm, edx, eax, Map::kHasIndexedInterceptor, &slow_call);
11667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateFastArrayLoad(
11689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      masm, edx, ecx, eax, edi, &check_number_dictionary, &slow_load);
116944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate = masm->isolate();
117044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate->counters();
117144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_call_generic_smi_fast(), 1);
11727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&do_call);
11747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // receiver in edx is not used after this point.
11757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // ecx: key
11767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // edi: function
11778defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateFunctionTailCall(masm, argc, &slow_call);
11787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&check_number_dictionary);
11807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // eax: elements
11817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // ecx: smi key
11827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Check whether the elements is a number dictionary.
1183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ CheckMap(eax,
1184257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              isolate->factory()->hash_table_map(),
1185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              &slow_load,
1186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              DONT_DO_SMI_CHECK);
11877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(ebx, ecx);
11887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ SmiUntag(ebx);
11897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // ebx: untagged index
11907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Receiver in edx will be clobbered, need to reload it on miss.
11913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ LoadFromNumberDictionary(
11923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      &slow_reload_receiver, eax, ecx, ebx, edx, edi, edi);
119344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_call_generic_smi_dict(), 1);
11947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&do_call);
11957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&slow_reload_receiver);
11977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
11987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&slow_load);
12007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // This branch is taken when calling KeyedCallIC_Miss is neither required
12017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // nor beneficial.
120244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_call_generic_slow_load(), 1);
12033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
12053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
12063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(ecx);  // save the key
12073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(edx);  // pass the receiver
12083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(ecx);  // pass the key
12093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallRuntime(Runtime::kKeyedGetProperty, 2);
12103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ pop(ecx);  // restore the key
12113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Leave the internal frame.
12123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
12133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(edi, eax);
12157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&do_call);
12167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&check_string);
12187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateKeyStringCheck(masm, ecx, eax, ebx, &index_string, &slow_call);
12197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // The key is known to be a symbol.
12217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // If the receiver is a regular JS object with slow properties then do
12227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // a quick inline probe of the receiver's dictionary.
12237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Otherwise do the monomorphic cache probe.
12248defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateKeyedLoadReceiverCheck(
12258defd9ff6930b4e24729971a61cf7469daf119beSteve Block      masm, edx, eax, Map::kHasNamedInterceptor, &lookup_monomorphic_cache);
12267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset));
122844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ CheckMap(ebx,
122944f0eee88ff00398ff7f715fab053374d808c90dSteve Block              isolate->factory()->hash_table_map(),
123044f0eee88ff00398ff7f715fab053374d808c90dSteve Block              &lookup_monomorphic_cache,
1231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              DONT_DO_SMI_CHECK);
12327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12338defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateDictionaryLoad(masm, &slow_load, ebx, ecx, eax, edi, edi);
123444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_call_generic_lookup_dict(), 1);
12357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&do_call);
12367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&lookup_monomorphic_cache);
123844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1);
12393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallICBase::GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC,
12403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            Code::kNoExtraICState);
12417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Fall through on miss.
12427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&slow_call);
12447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // This branch is taken if:
12457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // - the receiver requires boxing or access check,
12467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // - the key is neither smi nor symbol,
12477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // - the value loaded is not a function,
12487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // - there is hope that the runtime will create a monomorphic call stub
12497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //   that will get fetched next time.
125044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_call_generic_slow(), 1);
12517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateMiss(masm, argc);
12527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ bind(&index_string);
125480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ IndexFromHash(ebx, ecx);
12559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Now jump to the place where smi keys are handled.
12569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ jmp(&index_smi);
12577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
12587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
12603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedCallIC::GenerateNonStrictArguments(MacroAssembler* masm,
12613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                             int argc) {
12623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ----------- S t a t e -------------
12633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- ecx                 : name
12643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- esp[0]              : return address
12653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
12663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- ...
12673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- esp[(argc + 1) * 4] : receiver
12683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
12693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label slow, notin;
12703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Factory* factory = masm->isolate()->factory();
12713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
12723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Operand mapped_location =
12733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      GenerateMappedArgumentsLookup(masm, edx, ecx, ebx, eax, &notin, &slow);
12743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(edi, mapped_location);
12753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  GenerateFunctionTailCall(masm, argc, &slow);
12763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&notin);
12773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // The unmapped lookup expects that the parameter map is in ebx.
12783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Operand unmapped_location =
12793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      GenerateUnmappedArgumentsLookup(masm, ecx, ebx, eax, &slow);
12803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmp(unmapped_location, factory->the_hole_value());
12813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(equal, &slow);
12823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ mov(edi, unmapped_location);
12833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  GenerateFunctionTailCall(masm, argc, &slow);
12843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&slow);
12853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  GenerateMiss(masm, argc);
12863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
12873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
12883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
12897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) {
12909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // ----------- S t a t e -------------
12919dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  //  -- ecx                 : name
12929dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  //  -- esp[0]              : return address
12939dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
12949dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  //  -- ...
12959dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  //  -- esp[(argc + 1) * 4] : receiver
12969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // -----------------------------------
12979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1298e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Check if the name is a string.
1299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Label miss;
13003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(ecx, &miss);
1301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Condition cond = masm->IsObjectStringType(ecx, eax, eax);
1302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ j(NegateCondition(cond), &miss);
13033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallICBase::GenerateNormal(masm, argc);
1304e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&miss);
13057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  GenerateMiss(masm, argc);
13067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
13077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
13087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1311402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : receiver
1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Probe the stub cache.
1317589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, MONOMORPHIC);
131844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, eax, ecx, ebx,
131944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                  edx);
1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Cache miss: Jump to runtime.
1322402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateMiss(masm);
1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateNormal(MacroAssembler* masm) {
1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1328402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : receiver
1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
13328defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Label miss;
1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13348defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateStringDictionaryReceiverCheck(masm, eax, edx, ebx, &miss);
1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13368defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // edx: elements
1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Search the dictionary placing the result in eax.
13388defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateDictionaryLoad(masm, &miss, edx, ecx, edi, ebx, eax);
1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Cache miss: Jump to runtime.
1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1343402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateMiss(masm);
1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateMiss(MacroAssembler* masm) {
1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1349402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : receiver
1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
135444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(masm->isolate()->counters()->load_miss(), 1);
13558defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(ebx);
1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(eax);  // receiver
1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ecx);  // name
1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ebx);  // return address
1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform tail call to the entry.
136244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference ref =
136344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate());
13646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallExternalReference(ref, 2, 1);
1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadIC::GenerateMiss(MacroAssembler* masm, bool force_generic) {
1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1370402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
1371402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
137544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(masm->isolate()->counters()->keyed_load_miss(), 1);
13768defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1377402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ pop(ebx);
1378402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(edx);  // receiver
1379402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(eax);  // name
1380402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(ebx);  // return address
1381402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1382402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Perform tail call to the entry.
1383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExternalReference ref = force_generic
1384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? ExternalReference(IC_Utility(kKeyedLoadIC_MissForceGeneric),
1385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          masm->isolate())
1386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate());
13876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallExternalReference(ref, 2, 1);
1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1391402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1393402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- eax    : key
1394402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //  -- edx    : receiver
1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(ebx);
1399402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(edx);  // receiver
1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(eax);  // name
1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ebx);  // return address
1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform tail call to the entry.
14046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid StoreIC::GenerateMegamorphic(MacroAssembler* masm,
1409e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                  StrictModeFlag strict_mode) {
1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- eax    : value
1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
14134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- edx    : receiver
1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1417589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Code::Flags flags =
1418589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Code::ComputeFlags(Code::STORE_IC, MONOMORPHIC, strict_mode);
141944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx,
142044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                  no_reg);
1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Cache miss: Jump to runtime.
14234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  GenerateMiss(masm);
1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid StoreIC::GenerateMiss(MacroAssembler* masm) {
1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- eax    : value
1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- ecx    : name
14314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- edx    : receiver
1432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
1433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(ebx);
14364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ push(edx);
1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ecx);
1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(eax);
1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ebx);
1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform tail call to the entry.
144244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference ref =
144344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(IC_Utility(kStoreIC_Miss), masm->isolate());
14446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallExternalReference(ref, 3, 1);
14456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
14466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14486ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid StoreIC::GenerateArrayLength(MacroAssembler* masm) {
14496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
14506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- eax    : value
14516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ecx    : name
14526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- edx    : receiver
14536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- esp[0] : return address
14546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
14556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //
14563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // This accepts as a receiver anything JSArray::SetElementsLength accepts
145744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // (currently anything except for external arrays which means anything with
14583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // elements of FixedArray type).  Value must be a number, but only smis are
14593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // accepted as the most common case.
14606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss;
14626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register receiver = edx;
14646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register value = eax;
14656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register scratch = ebx;
14666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the receiver isn't a smi.
14683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(receiver, &miss);
14696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the object is a JS array.
14716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
1472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
14736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that elements are FixedArray.
1475756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // We rely on StoreIC_ArrayLength below to deal with all types of
1476756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // fast elements (including COW).
14776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(scratch, FieldOperand(receiver, JSArray::kElementsOffset));
14786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch);
1479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss);
14806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that the array has fast properties, otherwise the length
14823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // property might have been redefined.
14833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(scratch, FieldOperand(receiver, JSArray::kPropertiesOffset));
14843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CompareRoot(FieldOperand(scratch, FixedArray::kMapOffset),
14853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 Heap::kHashTableMapRootIndex);
14863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(equal, &miss);
14873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that value is a smi.
14893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfNotSmi(value, &miss);
14906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Prepare tail call to StoreIC_ArrayLength.
14926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ pop(scratch);
14936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(receiver);
14946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(value);
14956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(scratch);  // return address
14966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
149744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference ref =
149844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(IC_Utility(kStoreIC_ArrayLength), masm->isolate());
14996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallExternalReference(ref, 2, 1);
15006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss);
15026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  GenerateMiss(masm);
1504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15078defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid StoreIC::GenerateNormal(MacroAssembler* masm) {
15088defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // ----------- S t a t e -------------
15098defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //  -- eax    : value
15108defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //  -- ecx    : name
15118defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //  -- edx    : receiver
15128defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //  -- esp[0] : return address
15138defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // -----------------------------------
15148defd9ff6930b4e24729971a61cf7469daf119beSteve Block
15158defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Label miss, restore_miss;
15168defd9ff6930b4e24729971a61cf7469daf119beSteve Block
15178defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateStringDictionaryReceiverCheck(masm, edx, ebx, edi, &miss);
15188defd9ff6930b4e24729971a61cf7469daf119beSteve Block
15198defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // A lot of registers are needed for storing to slow case
15208defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // objects. Push and restore receiver but rely on
15218defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // GenerateDictionaryStore preserving the value and name.
15228defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ push(edx);
15238defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateDictionaryStore(masm, &restore_miss, ebx, ecx, eax, edx, edi);
15248defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ Drop(1);
152544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm->isolate()->counters();
152644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->store_normal_hit(), 1);
15278defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ ret(0);
15288defd9ff6930b4e24729971a61cf7469daf119beSteve Block
15298defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ bind(&restore_miss);
15308defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ pop(edx);
15318defd9ff6930b4e24729971a61cf7469daf119beSteve Block
15328defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ bind(&miss);
153344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->store_normal_miss(), 1);
15348defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateMiss(masm);
15358defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
15368defd9ff6930b4e24729971a61cf7469daf119beSteve Block
15378defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1538e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid StoreIC::GenerateGlobalProxy(MacroAssembler* masm,
1539e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                  StrictModeFlag strict_mode) {
1540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // ----------- S t a t e -------------
1541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- eax    : value
1542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- ecx    : name
1543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- edx    : receiver
1544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- esp[0] : return address
1545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // -----------------------------------
1546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ pop(ebx);
1547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ push(edx);
1548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ push(ecx);
1549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ push(eax);
1550e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ push(Immediate(Smi::FromInt(NONE)));  // PropertyAttributes
1551e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ push(Immediate(Smi::FromInt(strict_mode)));
1552e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ push(ebx);  // return address
1553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Do tail-call to runtime routine.
1555e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
1556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1559e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
1560e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                              StrictModeFlag strict_mode) {
1561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- eax    : value
15636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ecx    : key
15646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- edx    : receiver
1565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
1566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ pop(ebx);
15696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(edx);
1570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ecx);
15716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(eax);
1572e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ push(Immediate(Smi::FromInt(NONE)));         // PropertyAttributes
1573e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ push(Immediate(Smi::FromInt(strict_mode)));  // Strict mode.
1574e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ push(ebx);   // return address
1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do tail-call to runtime routine.
1577e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1581257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedStoreIC::GenerateMiss(MacroAssembler* masm, bool force_generic) {
1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- eax    : value
15846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- ecx    : key
15856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- edx    : receiver
1586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- esp[0] : return address
1587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ pop(ebx);
15906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(edx);
1591402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(ecx);
15926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(eax);
15936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(ebx);
1594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Do tail-call to runtime routine.
1596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExternalReference ref = force_generic
1597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? ExternalReference(IC_Utility(kKeyedStoreIC_MissForceGeneric),
1598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          masm->isolate())
1599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : ExternalReference(IC_Utility(kKeyedStoreIC_Miss), masm->isolate());
1600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ TailCallExternalReference(ref, 3, 1);
1601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedStoreIC::GenerateSlow(MacroAssembler* masm) {
1605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
1606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- eax    : value
1607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ecx    : key
1608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- edx    : receiver
1609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- esp[0] : return address
1610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
1611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ pop(ebx);
1613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ push(edx);
1614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ push(ecx);
1615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ push(eax);
1616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ push(ebx);   // return address
1617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Do tail-call to runtime routine.
1619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExternalReference ref(IC_Utility(kKeyedStoreIC_Slow), masm->isolate());
16206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallExternalReference(ref, 3, 1);
1621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
16243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid KeyedStoreIC::GenerateTransitionElementsSmiToDouble(MacroAssembler* masm) {
16253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ----------- S t a t e -------------
16263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //  -- ebx    : target map
16273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //  -- edx    : receiver
16283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //  -- esp[0] : return address
16293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // -----------------------------------
16303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Must return the modified receiver in eax.
16313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!FLAG_trace_elements_transitions) {
16323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label fail;
16333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsTransitionGenerator::GenerateSmiOnlyToDouble(masm, &fail);
16343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(eax, edx);
16353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Ret();
16363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&fail);
16373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
16383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ pop(ebx);
16403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(edx);
16413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(ebx);  // return address
16423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Leaving the code managed by the register allocator and return to the
16433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // convention of using esi as context register.
16443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
16453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ TailCallRuntime(Runtime::kTransitionElementsSmiToDouble, 1, 1);
16463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
16473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid KeyedStoreIC::GenerateTransitionElementsDoubleToObject(
16503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MacroAssembler* masm) {
16513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ----------- S t a t e -------------
16523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //  -- ebx    : target map
16533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //  -- edx    : receiver
16543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //  -- esp[0] : return address
16553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // -----------------------------------
16563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Must return the modified receiver in eax.
16573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!FLAG_trace_elements_transitions) {
16583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label fail;
16593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsTransitionGenerator::GenerateDoubleToObject(masm, &fail);
16603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(eax, edx);
16613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Ret();
16623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&fail);
16633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
16643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ pop(ebx);
16663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(edx);
16673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(ebx);  // return address
16683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Leaving the code managed by the register allocator and return to the
16693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // convention of using esi as context register.
16703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
16713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ TailCallRuntime(Runtime::kTransitionElementsDoubleToObject, 1, 1);
16723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
16733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __
1676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochCondition CompareIC::ComputeCondition(Token::Value op) {
1679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  switch (op) {
1680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::EQ_STRICT:
1681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::EQ:
1682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return equal;
1683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::LT:
1684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return less;
1685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::GT:
16863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return greater;
1687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::LTE:
16883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return less_equal;
1689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::GTE:
1690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return greater_equal;
1691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    default:
1692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      UNREACHABLE();
1693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return no_condition;
1694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic bool HasInlinedSmiCode(Address address) {
1699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The address of the instruction following the call.
1700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Address test_instruction_address =
1701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      address + Assembler::kCallTargetAddressOffset;
1702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // If the instruction following the call is not a test al, nothing
1704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // was inlined.
1705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return *test_instruction_address == Assembler::kTestAlByte;
1706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) {
1710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HandleScope scope;
1711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<Code> rewritten;
1712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  State previous_state = GetState();
1713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  State state = TargetState(previous_state, HasInlinedSmiCode(address()), x, y);
1715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (state == GENERIC) {
1716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompareStub stub(GetCondition(), strict(), NO_COMPARE_FLAGS);
1717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    rewritten = stub.GetCode();
1718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
1719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ICCompareStub stub(op_, state);
17203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (state == KNOWN_OBJECTS) {
17213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      stub.set_known_map(Handle<Map>(Handle<JSObject>::cast(x)->map()));
17223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    rewritten = stub.GetCode();
1724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  set_target(*rewritten);
1726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
1728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_ic) {
1729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF("[CompareIC (%s->%s)#%s]\n",
1730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           GetStateName(previous_state),
1731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           GetStateName(state),
1732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           Token::Name(op_));
1733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
1735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Activate inlined smi code.
1737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (previous_state == UNINITIALIZED) {
1738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PatchInlinedSmiCode(address());
1739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid PatchInlinedSmiCode(Address address) {
1744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The address of the instruction following the call.
1745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Address test_instruction_address =
1746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      address + Assembler::kCallTargetAddressOffset;
1747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // If the instruction following the call is not a test al, nothing
1749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // was inlined.
1750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (*test_instruction_address != Assembler::kTestAlByte) {
1751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(*test_instruction_address == Assembler::kNopByte);
1752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return;
1753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Address delta_address = test_instruction_address + 1;
1756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The delta to the start of the map check instruction and the
1757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // condition code uses at the patched jump.
1758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int8_t delta = *reinterpret_cast<int8_t*>(delta_address);
1759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_ic) {
1760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF("[  patching ic at %p, test=%p, delta=%d\n",
1761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           address, test_instruction_address, delta);
1762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Patch with a short conditional jump. There must be a
1765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // short jump-if-carry/not-carry at this position.
1766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Address jmp_address = test_instruction_address - delta;
1767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(*jmp_address == Assembler::kJncShortOpcode ||
1768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch         *jmp_address == Assembler::kJcShortOpcode);
1769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Condition cc = *jmp_address == Assembler::kJncShortOpcode
1770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ? not_zero
1771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : zero;
1772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc);
1773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
1777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_IA32
1779