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_X64)
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  __ cmpb(type, Immediate(JS_GLOBAL_OBJECT_TYPE));
538defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ j(equal, global_object);
548defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ cmpb(type, Immediate(JS_BUILTINS_OBJECT_TYPE));
558defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ j(equal, global_object);
568defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ cmpb(type, Immediate(JS_GLOBAL_PROXY_TYPE));
578defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ 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  __ JumpIfSmi(receiver, miss);
758defd9ff6930b4e24729971a61cf7469daf119beSteve Block
768defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Check that the receiver is a valid JS object.
778defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ movq(r1, FieldOperand(receiver, HeapObject::kMapOffset));
788defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ movb(r0, FieldOperand(r1, Map::kInstanceTypeOffset));
793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmpb(r0, Immediate(FIRST_SPEC_OBJECT_TYPE));
808defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ j(below, miss);
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
828defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // If this assert fails, we have to check upper bound too.
833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE);
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
858defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateGlobalInstanceTypeCheck(masm, r0, miss);
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
878defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Check for non-global object that requires access check.
888defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ testb(FieldOperand(r1, Map::kBitFieldOffset),
898defd9ff6930b4e24729971a61cf7469daf119beSteve Block           Immediate((1 << Map::kIsAccessCheckNeeded) |
908defd9ff6930b4e24729971a61cf7469daf119beSteve Block                     (1 << Map::kHasNamedInterceptor)));
918defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ j(not_zero, miss);
928defd9ff6930b4e24729971a61cf7469daf119beSteve Block
938defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ movq(r0, FieldOperand(receiver, JSObject::kPropertiesOffset));
948defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ CompareRoot(FieldOperand(r0, HeapObject::kMapOffset),
958defd9ff6930b4e24729971a61cf7469daf119beSteve Block                 Heap::kHashTableMapRootIndex);
968defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ j(not_equal, miss);
978defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
98e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1018defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Helper function used to load a property from a dictionary backing storage.
1028defd9ff6930b4e24729971a61cf7469daf119beSteve Block// This function may return false negatives, so miss_label
1038defd9ff6930b4e24729971a61cf7469daf119beSteve Block// must always call a backup property load that is complete.
1048defd9ff6930b4e24729971a61cf7469daf119beSteve Block// This function is safe to call if name is not a symbol, and will jump to
1058defd9ff6930b4e24729971a61cf7469daf119beSteve Block// the miss_label in that case.
1068defd9ff6930b4e24729971a61cf7469daf119beSteve Block// The generated code assumes that the receiver has slow properties,
1078defd9ff6930b4e24729971a61cf7469daf119beSteve Block// is not a global object and does not have interceptors.
1088defd9ff6930b4e24729971a61cf7469daf119beSteve Blockstatic void GenerateDictionaryLoad(MacroAssembler* masm,
1098defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                   Label* miss_label,
1108defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                   Register elements,
1118defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                   Register name,
1128defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                   Register r0,
1138defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                   Register r1,
1148defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                   Register result) {
1158defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Register use:
1168defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //
1178defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // elements - holds the property dictionary on entry and is unchanged.
1188defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //
1198defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // name - holds the name of the property on entry and is unchanged.
1208defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //
1218defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // r0   - used to hold the capacity of the property dictionary.
1228defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //
1238defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // r1   - used to hold the index into the property dictionary.
1248defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //
1258defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // result - holds the result on exit if the load succeeded.
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, r1, times_pointer_size,
1478defd9ff6930b4e24729971a61cf7469daf119beSteve Block                  kDetailsOffset - kHeapObjectTag),
148589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          Smi::FromInt(PropertyDetails::TypeField::kMask));
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_zero, miss_label);
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the value at the masked, scaled index.
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kValueOffset = kElementsStartOffset + kPointerSize;
1539dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ movq(result,
1548defd9ff6930b4e24729971a61cf7469daf119beSteve Block          Operand(elements, r1, times_pointer_size,
1558defd9ff6930b4e24729971a61cf7469daf119beSteve Block                  kValueOffset - kHeapObjectTag));
1568defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
1578defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1588defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1598defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Helper function used to store a property to a dictionary backing
1608defd9ff6930b4e24729971a61cf7469daf119beSteve Block// storage. This function may fail to store a property even though it
1618defd9ff6930b4e24729971a61cf7469daf119beSteve Block// is in the dictionary, so code at miss_label must always call a
1628defd9ff6930b4e24729971a61cf7469daf119beSteve Block// backup property store that is complete. This function is safe to
1638defd9ff6930b4e24729971a61cf7469daf119beSteve Block// call if name is not a symbol, and will jump to the miss_label in
1648defd9ff6930b4e24729971a61cf7469daf119beSteve Block// that case. The generated code assumes that the receiver has slow
1658defd9ff6930b4e24729971a61cf7469daf119beSteve Block// properties, is not a global object and does not have interceptors.
1668defd9ff6930b4e24729971a61cf7469daf119beSteve Blockstatic void GenerateDictionaryStore(MacroAssembler* masm,
1678defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                    Label* miss_label,
1688defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                    Register elements,
1698defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                    Register name,
1708defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                    Register value,
1718defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                    Register scratch0,
1728defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                    Register scratch1) {
1738defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Register use:
1748defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //
1758defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // elements - holds the property dictionary on entry and is clobbered.
1768defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //
1778defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // name - holds the name of the property on entry and is unchanged.
1788defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //
1798defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // value - holds the value to store and is unchanged.
1808defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //
1818defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // scratch0 - used for index into the property dictionary and is clobbered.
1828defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //
1838defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // scratch1 - used to hold the capacity of the property dictionary and is
1848defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //            clobbered.
1858defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Label done;
1868defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1878defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Probe the dictionary.
188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  StringDictionaryLookupStub::GeneratePositiveLookup(masm,
189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                     miss_label,
190257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                     &done,
191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                     elements,
192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                     name,
193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                     scratch0,
194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                     scratch1);
1958defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1968defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // If probing finds an entry in the dictionary, scratch0 contains the
1978defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // index into the dictionary. Check that the value is a normal
1988defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // property that is not read only.
1998defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ bind(&done);
2008defd9ff6930b4e24729971a61cf7469daf119beSteve Block  const int kElementsStartOffset =
2018defd9ff6930b4e24729971a61cf7469daf119beSteve Block      StringDictionary::kHeaderSize +
2028defd9ff6930b4e24729971a61cf7469daf119beSteve Block      StringDictionary::kElementsStartIndex * kPointerSize;
2038defd9ff6930b4e24729971a61cf7469daf119beSteve Block  const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
204589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  const int kTypeAndReadOnlyMask =
205589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      (PropertyDetails::TypeField::kMask |
206589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch       PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize;
2078defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ Test(Operand(elements,
2088defd9ff6930b4e24729971a61cf7469daf119beSteve Block                  scratch1,
2098defd9ff6930b4e24729971a61cf7469daf119beSteve Block                  times_pointer_size,
2108defd9ff6930b4e24729971a61cf7469daf119beSteve Block                  kDetailsOffset - kHeapObjectTag),
2118defd9ff6930b4e24729971a61cf7469daf119beSteve Block          Smi::FromInt(kTypeAndReadOnlyMask));
2128defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ j(not_zero, miss_label);
2138defd9ff6930b4e24729971a61cf7469daf119beSteve Block
2148defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Store the value at the masked, scaled index.
2158defd9ff6930b4e24729971a61cf7469daf119beSteve Block  const int kValueOffset = kElementsStartOffset + kPointerSize;
2168defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ lea(scratch1, Operand(elements,
2178defd9ff6930b4e24729971a61cf7469daf119beSteve Block                           scratch1,
2188defd9ff6930b4e24729971a61cf7469daf119beSteve Block                           times_pointer_size,
2198defd9ff6930b4e24729971a61cf7469daf119beSteve Block                           kValueOffset - kHeapObjectTag));
2208defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ movq(Operand(scratch1, 0), value);
2218defd9ff6930b4e24729971a61cf7469daf119beSteve Block
2228defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Update write barrier. Make sure not to clobber the value.
2238defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ movq(scratch0, value);
2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ RecordWrite(elements, scratch1, scratch0, kDontSaveFPRegs);
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid LoadIC::GenerateArrayLength(MacroAssembler* masm) {
2299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
2309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : receiver
2319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx    : name
2329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0] : return address
2339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
2349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  StubCompiler::GenerateLoadArrayLength(masm, rax, rdx, &miss);
2379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
2389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid LoadIC::GenerateStringLength(MacroAssembler* masm, bool support_wrappers) {
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
2449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : receiver
2459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx    : name
2469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0] : return address
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
2489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  StubCompiler::GenerateLoadStringLength(masm, rax, rdx, rbx, &miss,
2511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                         support_wrappers);
2529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
2539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
254402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
255402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
256402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
258402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // ----------- S t a t e -------------
2599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : receiver
2609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx    : name
2619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0] : return address
262402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // -----------------------------------
2639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Label miss;
264402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  StubCompiler::GenerateLoadFunctionPrototype(masm, rax, rdx, rbx, &miss);
2669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ bind(&miss);
2679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2719dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen// Checks the receiver for special cases (value type, slow case bits).
2729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen// Falls through for regular JS object.
2739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenstatic void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
2749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                           Register receiver,
2759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                           Register map,
2768defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                           int interceptor_bit,
2779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                           Label* slow) {
2789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Register use:
2799dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  //   receiver - holds the receiver and is unchanged.
2809dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Scratch registers:
2819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  //   map - used to hold the map of the receiver.
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object isn't a smi.
2849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ JumpIfSmi(receiver, slow);
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object is some kind of JS object EXCEPT JS Value type.
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // In the case that the object is a value-wrapper object,
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // we enter the runtime system to make sure that indexing
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // into string objects work as intended.
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
2919dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ CmpObjectType(receiver, JS_OBJECT_TYPE, map);
2929dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ j(below, slow);
293d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
294d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Check bit field.
2959dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ testb(FieldOperand(map, Map::kBitFieldOffset),
2968defd9ff6930b4e24729971a61cf7469daf119beSteve Block           Immediate((1 << Map::kIsAccessCheckNeeded) |
2978defd9ff6930b4e24729971a61cf7469daf119beSteve Block                     (1 << interceptor_bit)));
2989dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ j(not_zero, slow);
2999dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3019dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3029dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen// Loads an indexed element from a fast case array.
303756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick// If not_fast_array is NULL, doesn't perform the elements map check.
3049dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenstatic void GenerateFastArrayLoad(MacroAssembler* masm,
3059dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                  Register receiver,
3069dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                  Register key,
3079dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                  Register elements,
3089dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                  Register scratch,
3099dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                  Register result,
3109dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                  Label* not_fast_array,
3119dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                  Label* out_of_range) {
3129dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Register use:
3139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  //
3149dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // receiver - holds the receiver on entry.
3159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  //            Unchanged unless 'result' is the same register.
3169dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  //
3179dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // key      - holds the smi key on entry.
3189dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  //            Unchanged unless 'result' is the same register.
3199dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  //
3209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // elements - holds the elements of the receiver on exit.
3219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  //
3229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // result   - holds the result on exit if the load succeeded.
3239dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  //            Allowed to be the the same as 'receiver' or 'key'.
3249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  //            Unchanged on bailout so 'receiver' and 'key' can be safely
3259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  //            used by further computation.
3269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  //
3279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Scratch registers:
3289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  //
3299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  //   scratch - used to hold elements of the receiver and the loaded value.
3309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ movq(elements, FieldOperand(receiver, JSObject::kElementsOffset));
332756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (not_fast_array != NULL) {
333756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    // Check that the object is in fast mode and writable.
334756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
335756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                   Heap::kFixedArrayMapRootIndex);
336756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ j(not_equal, not_fast_array);
337756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  } else {
338756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    __ AssertFastElements(elements);
339756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the key (index) is within bounds.
3419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ SmiCompare(key, FieldOperand(elements, FixedArray::kLengthOffset));
3429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Unsigned comparison rejects negative indices.
3439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ j(above_equal, out_of_range);
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fast case: Do the load.
3459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  SmiIndex index = masm->SmiToIndex(scratch, key, kPointerSizeLog2);
3469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ movq(scratch, FieldOperand(elements,
3479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                index.reg,
3489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                index.scale,
3499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                FixedArray::kHeaderSize));
3509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ CompareRoot(scratch, Heap::kTheHoleValueRootIndex);
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // In case the loaded value is the_hole we have to consult GetProperty
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to ensure the prototype chain is searched.
3539dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ j(equal, out_of_range);
3549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  if (!result.is(scratch)) {
3559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    __ movq(result, scratch);
3569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
3579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
3589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3599dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen// Checks whether a key is an array index string or a symbol string.
3619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen// Falls through if the key is a symbol.
3629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenstatic void GenerateKeyStringCheck(MacroAssembler* masm,
3639dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                   Register key,
3649dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                   Register map,
3659dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                   Register hash,
3669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                   Label* index_string,
3679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                   Label* not_symbol) {
3689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Register use:
3699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  //   key - holds the key and is unchanged. Assumed to be non-smi.
3709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Scratch registers:
3719dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  //   map - used to hold the map of the key.
3729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  //   hash - used to hold the hash of the key.
3739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ CmpObjectType(key, FIRST_NONSTRING_TYPE, map);
3749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ j(above_equal, not_symbol);
3759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Is the string an array index, with cached numeric value?
3769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ movl(hash, FieldOperand(key, String::kHashFieldOffset));
3779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ testl(hash, Immediate(String::kContainsCachedArrayIndexMask));
3789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ j(zero, index_string);  // The value in hash is used at jump target.
3799dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3809dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Is the string a symbol?
38169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSymbolTag != 0);
3829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ testb(FieldOperand(map, Map::kInstanceTypeOffset),
3839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen           Immediate(kIsSymbolMask));
3849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ j(zero, not_symbol);
3859dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
3869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3879dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3889dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3899dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
3909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // ----------- S t a t e -------------
3919dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  //  -- rax    : key
3929dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  //  -- rdx    : receiver
3939dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  //  -- rsp[0] : return address
3949dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // -----------------------------------
395bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Label slow, check_string, index_smi, index_string, property_array_property;
39644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Label probe_dictionary, check_number_dictionary;
3979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3989dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Check that the key is a smi.
3999dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ JumpIfNotSmi(rax, &check_string);
4009dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ bind(&index_smi);
4019dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Now the key is known to be a smi. This place is also jumped to from below
4029dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // where a numeric string is converted to a smi.
4039dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
4048defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateKeyedLoadReceiverCheck(
4058defd9ff6930b4e24729971a61cf7469daf119beSteve Block      masm, rdx, rcx, Map::kHasIndexedInterceptor, &slow);
4068defd9ff6930b4e24729971a61cf7469daf119beSteve Block
4073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check the receiver's map to see if it has fast elements.
4083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CheckFastElements(rcx, &check_number_dictionary);
409756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
4109dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateFastArrayLoad(masm,
4119dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                        rdx,
4129dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                        rax,
4139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                        rcx,
4149dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                        rbx,
4159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                        rax,
416756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                        NULL,
4179dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                        &slow);
41844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm->isolate()->counters();
41944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_generic_smi(), 1);
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&check_number_dictionary);
42344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ SmiToInteger32(rbx, rax);
42444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
42544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check whether the elements is a number dictionary.
4277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // rdx: receiver
4287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // rax: key
4297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // rbx: key as untagged int32
4306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // rcx: elements
4316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
4326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                 Heap::kHashTableMapRootIndex);
4336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ j(not_equal, &slow);
4343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ LoadFromNumberDictionary(&slow, rcx, rax, rbx, r9, rdi, rax);
4356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ret(0);
4366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&slow);
4387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Slow case: Jump to runtime.
4397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // rdx: receiver
4407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // rax: key
44144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_generic_slow(), 1);
442402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateRuntimeGetProperty(masm);
4437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&check_string);
4459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateKeyStringCheck(masm, rax, rcx, rbx, &index_string, &slow);
446e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4478defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateKeyedLoadReceiverCheck(
4488defd9ff6930b4e24729971a61cf7469daf119beSteve Block      masm, rdx, rcx, Map::kHasNamedInterceptor, &slow);
4498defd9ff6930b4e24729971a61cf7469daf119beSteve Block
450e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // If the receiver is a fast-case object, check the keyed lookup
451e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // cache. Otherwise probe the dictionary leaving result in rcx.
4527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ movq(rbx, FieldOperand(rdx, JSObject::kPropertiesOffset));
4537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
4547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                 Heap::kHashTableMapRootIndex);
455e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(equal, &probe_dictionary);
456e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
457e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Load the map of the receiver, compute the keyed lookup cache hash
458e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // based on 32 bits of the map pointer and the string hash.
4597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
4607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ movl(rcx, rbx);
4617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ shr(rcx, Immediate(KeyedLookupCache::kMapHashShift));
4627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ movl(rdi, FieldOperand(rax, String::kHashFieldOffset));
4637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ shr(rdi, Immediate(String::kHashShift));
4647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ xor_(rcx, rdi);
4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int mask = (KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask);
4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ and_(rcx, Immediate(mask));
467e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
468e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Load the key (consisting of map and symbol) from the cache and
469e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // check for match.
4703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label load_in_object_property;
4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket;
4723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label hit_on_nth_entry[kEntriesPerBucket];
473e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ExternalReference cache_keys
47444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      = ExternalReference::keyed_lookup_cache_keys(masm->isolate());
4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < kEntriesPerBucket - 1; i++) {
4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label try_next_entry;
4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movq(rdi, rcx);
4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ shl(rdi, Immediate(kPointerSizeLog2 + 1));
4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadAddress(kScratchRegister, cache_keys);
4813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int off = kPointerSize * i * 2;
4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmpq(rbx, Operand(kScratchRegister, rdi, times_1, off));
4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &try_next_entry);
4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmpq(rax, Operand(kScratchRegister, rdi, times_1, off + kPointerSize));
4853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(equal, &hit_on_nth_entry[i]);
4863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&try_next_entry);
4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int off = kPointerSize * (kEntriesPerBucket - 1) * 2;
4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmpq(rbx, Operand(kScratchRegister, rdi, times_1, off));
491e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(not_equal, &slow);
4923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmpq(rax, Operand(kScratchRegister, rdi, times_1, off + kPointerSize));
493e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ j(not_equal, &slow);
494e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
495bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Get field offset, which is a 32-bit integer.
496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ExternalReference cache_field_offsets
49744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      = ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate());
4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Hit on nth entry.
5003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = kEntriesPerBucket - 1; i >= 0; i--) {
5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&hit_on_nth_entry[i]);
5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (i != 0) {
5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ addl(rcx, Immediate(i));
5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadAddress(kScratchRegister, cache_field_offsets);
5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movl(rdi, Operand(kScratchRegister, rcx, times_4, 0));
5073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movzxbq(rcx, FieldOperand(rbx, Map::kInObjectPropertiesOffset));
5083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ subq(rdi, rcx);
5093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(above_equal, &property_array_property);
5103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (i != 0) {
5113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(&load_in_object_property);
5123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
514e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
515e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Load in-object property.
5163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&load_in_object_property);
5177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ movzxbq(rcx, FieldOperand(rbx, Map::kInstanceSizeOffset));
5187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ addq(rcx, rdi);
5197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ movq(rax, FieldOperand(rdx, rcx, times_pointer_size, 0));
52044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1);
521e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ ret(0);
522e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
523bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Load property array property.
524bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ bind(&property_array_property);
525bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ movq(rax, FieldOperand(rdx, JSObject::kPropertiesOffset));
526bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ movq(rax, FieldOperand(rax, rdi, times_pointer_size,
527bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                            FixedArray::kHeaderSize));
52844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1);
529bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  __ ret(0);
530bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
531e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Do a quick inline probe of the receiver's dictionary, if it
532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // exists.
533e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ bind(&probe_dictionary);
5347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // rdx: receiver
5357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // rax: key
5368defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // rbx: elements
5378defd9ff6930b4e24729971a61cf7469daf119beSteve Block
5388defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ movq(rcx, FieldOperand(rdx, JSObject::kMapOffset));
5398defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ movb(rcx, FieldOperand(rcx, Map::kInstanceTypeOffset));
5408defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateGlobalInstanceTypeCheck(masm, rcx, &slow);
5418defd9ff6930b4e24729971a61cf7469daf119beSteve Block
5428defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateDictionaryLoad(masm, &slow, rbx, rax, rcx, rdi, rax);
54344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_generic_symbol(), 1);
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
5459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&index_string);
54780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ IndexFromHash(rbx, rax);
5487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ jmp(&index_smi);
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
552e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid KeyedLoadIC::GenerateString(MacroAssembler* masm) {
553e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // ----------- S t a t e -------------
5547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rax    : key
5557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rdx    : receiver
556e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- rsp[0] : return address
557e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // -----------------------------------
5586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss;
5596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register receiver = rdx;
5616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register index = rax;
5623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = rcx;
5637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Register result = rax;
5647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
5657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringCharAtGenerator char_at_generator(receiver,
5667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                          index,
5673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                          scratch,
5687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                          result,
5697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                          &miss,  // When not a string.
5707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                          &miss,  // When not a number.
5710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                          &miss,  // When index out of range.
5727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                                          STRING_INDEX_IS_ARRAY_INDEX);
5737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  char_at_generator.GenerateFast(masm);
5747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ ret(0);
5756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StubRuntimeCallHelper call_helper;
5777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  char_at_generator.GenerateSlow(masm, call_helper);
5786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss);
580257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateMiss(masm, false);
581e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
582e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
583e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
584402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
5867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rax    : key
5877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rdx    : receiver
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0] : return address
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
590402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Label slow;
591402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
592402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Check that the receiver isn't a smi.
5937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ JumpIfSmi(rdx, &slow);
594402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
595f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // Check that the key is an array index, that is Uint32.
596f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  STATIC_ASSERT(kSmiValueSize <= 32);
597f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ JumpUnlessNonNegativeSmi(rax, &slow);
598402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
599402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Get the map of the receiver.
6007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset));
601402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
602402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Check that it has indexed interceptor and access checks
603402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // are not enabled for this object.
6047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ movb(rcx, FieldOperand(rcx, Map::kBitFieldOffset));
6057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ andb(rcx, Immediate(kSlowCaseBitFieldMask));
6067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ cmpb(rcx, Immediate(1 << Map::kHasIndexedInterceptor));
607402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ j(not_zero, &slow);
608402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
609402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Everything is fine, call runtime.
6107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ pop(rcx);
6117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ push(rdx);  // receiver
612402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ push(rax);  // key
6137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ push(rcx);  // return address
614402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
615402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Perform tail call to the entry.
61644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ TailCallExternalReference(
61744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor),
61844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        masm->isolate()),
61944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      2,
62044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      1);
621402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
622402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ bind(&slow);
623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateMiss(masm, false);
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
627e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
628e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   StrictModeFlag strict_mode) {
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
630f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- rax     : value
631f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- rcx     : key
632f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- rdx     : receiver
633f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  //  -- rsp[0]  : return address
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
6353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label slow, slow_with_tagged_index, fast, array, extra, check_extra_double;
6363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label fast_object_with_map_check, fast_object_without_map_check;
6373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label fast_double_with_map_check, fast_double_without_map_check;
6383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label transition_smi_elements, finish_object_store, non_double_value;
6393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label transition_double_elements;
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the object isn't a smi.
6429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ JumpIfSmi(rdx, &slow_with_tagged_index);
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the map from the receiver.
6443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(r9, FieldOperand(rdx, HeapObject::kMapOffset));
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the receiver does not require access checks.  We need
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to do this because this generic stub does not perform map checks.
6473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ testb(FieldOperand(r9, Map::kBitFieldOffset),
648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           Immediate(1 << Map::kIsAccessCheckNeeded));
6499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ j(not_zero, &slow_with_tagged_index);
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the key is a smi.
6519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ JumpIfNotSmi(rcx, &slow_with_tagged_index);
6529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ SmiToInteger32(rcx, rcx);
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CmpInstanceType(r9, JS_ARRAY_TYPE);
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(equal, &array);
6563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the object is some kind of JSObject.
6573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CmpInstanceType(r9, FIRST_JS_OBJECT_TYPE);
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(below, &slow);
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Object case: Check key against length in the elements array.
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rax: value
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rdx: JSObject
6639dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rcx: index
664f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
6653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check array bounds.
6669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), rcx);
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rax: value
668f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // rbx: FixedArray
6699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rcx: index
6703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(above, &fast_object_with_map_check);
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Slow case: call runtime.
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&slow);
6749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ Integer32ToSmi(rcx, rcx);
6759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ bind(&slow_with_tagged_index);
676e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  GenerateRuntimeSetProperty(masm, strict_mode);
6779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Never returns to here.
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Extra capacity case: Check if there is extra capacity to
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // perform the store and update the length. Used for adding one
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // element to the array by writing to array[array.length].
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&extra);
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rax: value
684f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // rdx: receiver (a JSArray)
685f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // rbx: receiver's elements array (a FixedArray)
6869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rcx: index
6873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // flags: smicompare (rdx.length(), rbx)
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &slow);  // do not leave holes in the array
6899dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), rcx);
6909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ j(below_equal, &slow);
6917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Increment index to get new length.
6923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(rdi, FieldOperand(rbx, HeapObject::kMapOffset));
6933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CompareRoot(rdi, Heap::kFixedArrayMapRootIndex);
6943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_equal, &check_extra_double);
6953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ leal(rdi, Operand(rcx, 1));
6963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rdi);
6973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&fast_object_without_map_check);
6983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&check_extra_double);
7003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // rdi: elements array's map
7013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CompareRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex);
7023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_equal, &slow);
703592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ leal(rdi, Operand(rcx, 1));
704592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rdi);
7053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&fast_double_without_map_check);
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Array case: Get the length and the elements array from the JS
708756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // array. Check that the array is in fast mode (and writable); if it
709756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // is the length is always a smi.
710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&array);
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rax: value
712f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // rdx: receiver (a JSArray)
7139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rcx: index
714f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the key against the length in the array, compute the
717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // address to store into and fall through to fast case.
7189dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ SmiCompareInteger32(FieldOperand(rdx, JSArray::kLengthOffset), rcx);
7193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ j(below_equal, &extra);
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fast case: Do the store.
7223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&fast_object_with_map_check);
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rax: value
724f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // rbx: receiver's elements array (a FixedArray)
7259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rcx: index
7263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // rdx: receiver (a JSArray)
7273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(rdi, FieldOperand(rbx, HeapObject::kMapOffset));
7283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CompareRoot(rdi, Heap::kFixedArrayMapRootIndex);
7293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_equal, &fast_double_with_map_check);
7303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&fast_object_without_map_check);
7313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Smi stores don't require further checks.
732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label non_smi_value;
7333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfNotSmi(rax, &non_smi_value);
7343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // It's irrelevant whether array is smi-only or not when writing a smi.
7359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ movq(FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize),
7363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block          rax);
7373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ ret(0);
7383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  __ bind(&non_smi_value);
7403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Writing a non-smi, check whether array allows non-smi elements.
7413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // r9: receiver's map
7423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckFastObjectElements(r9, &transition_smi_elements);
7433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&finish_object_store);
7443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize),
7453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          rax);
7463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(rdx, rax);  // Preserve the value which is returned.
7473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ RecordWriteArray(
7483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      rbx, rdx, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
749592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ ret(0);
7503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&fast_double_with_map_check);
7523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for fast double array case. If this fails, call through to the
7533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // runtime.
7543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // rdi: elements array's map
7553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CompareRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex);
7563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_equal, &slow);
7573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&fast_double_without_map_check);
7583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the value is a number, store it as a double in the FastDoubleElements
7593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // array.
7603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ StoreNumberToDoubleElements(rax, rbx, rcx, xmm0,
7613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 &transition_double_elements);
7623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ret(0);
7633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&transition_smi_elements);
7653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
7663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Transition the array appropriately depending on the value type.
7683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(r9, FieldOperand(rax, HeapObject::kMapOffset));
7693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CompareRoot(r9, Heap::kHeapNumberMapRootIndex);
7703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_equal, &non_double_value);
7713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Value is a double. Transition FAST_SMI_ONLY_ELEMENTS ->
7733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // FAST_DOUBLE_ELEMENTS and complete the store.
7743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS,
7753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         FAST_DOUBLE_ELEMENTS,
7763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         rbx,
7773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         rdi,
7783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         &slow);
7793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ElementsTransitionGenerator::GenerateSmiOnlyToDouble(masm, &slow);
7803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
7813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&fast_double_without_map_check);
7823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&non_double_value);
7843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Value is not a double, FAST_SMI_ONLY_ELEMENTS -> FAST_ELEMENTS
7853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS,
7863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         FAST_ELEMENTS,
7873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         rbx,
7883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         rdi,
7893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         &slow);
7903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ElementsTransitionGenerator::GenerateSmiOnlyToObject(masm);
7913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
7923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&finish_object_store);
7933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&transition_double_elements);
7953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a
7963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and
7973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS
7983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
7993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS,
8003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         FAST_ELEMENTS,
8013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         rbx,
8023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         rdi,
8033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         &slow);
8043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ElementsTransitionGenerator::GenerateDoubleToObject(masm, &slow);
8053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
8063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&finish_object_store);
8073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
8083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8109dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen// The generated code does not accept smi keys.
8119dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen// The generated code falls through if both probes miss.
8123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallICBase::GenerateMonomorphicCacheProbe(MacroAssembler* masm,
8133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               int argc,
8143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               Code::Kind kind,
8153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               Code::ExtraICState extra_state) {
816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
817402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rcx                      : function name
8189dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rdx                      : receiver
819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label number, non_number, non_string, boolean, probe, miss;
821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Probe the stub cache.
823b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Code::Flags flags = Code::ComputeFlags(kind,
824b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                         MONOMORPHIC,
8253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         extra_state,
826b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                         NORMAL,
827b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                         argc);
82844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, rdx, rcx, rbx,
82944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                  rax);
830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the stub cache probing failed, the receiver might be a value.
832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // For value objects, we use the map of the prototype objects for
833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the corresponding JSValue for the cache and that is what we need
834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to probe.
835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for number.
837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ JumpIfSmi(rdx, &number);
838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rbx);
839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &non_number);
840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&number);
841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StubCompiler::GenerateLoadGlobalFunctionPrototype(
842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      masm, Context::NUMBER_FUNCTION_INDEX, rdx);
843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(&probe);
844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for string.
846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&non_number);
847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CmpInstanceType(rbx, FIRST_NONSTRING_TYPE);
848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(above_equal, &non_string);
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StubCompiler::GenerateLoadGlobalFunctionPrototype(
850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      masm, Context::STRING_FUNCTION_INDEX, rdx);
851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(&probe);
852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for boolean.
854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&non_string);
855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CompareRoot(rdx, Heap::kTrueValueRootIndex);
856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(equal, &boolean);
857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CompareRoot(rdx, Heap::kFalseValueRootIndex);
858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, &miss);
859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&boolean);
860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StubCompiler::GenerateLoadGlobalFunctionPrototype(
861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      masm, Context::BOOLEAN_FUNCTION_INDEX, rdx);
862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Probe the stub cache for the value object.
864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&probe);
86544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, rdx, rcx, rbx,
86644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                  no_reg);
867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8728defd9ff6930b4e24729971a61cf7469daf119beSteve Blockstatic void GenerateFunctionTailCall(MacroAssembler* masm,
8738defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                     int argc,
8748defd9ff6930b4e24729971a61cf7469daf119beSteve Block                                     Label* miss) {
875402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // ----------- S t a t e -------------
876402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rcx                    : function name
8778defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // rdi                    : function
878402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[0]                 : return address
879402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[8]                 : argument argc
880402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[16]                : argument argc - 1
881402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // ...
882402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[argc * 8]          : argument 1
883402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[(argc + 1) * 8]    : argument 0 = receiver
884402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // -----------------------------------
8859dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ JumpIfSmi(rdi, miss);
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the value is a JavaScript function.
8879dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rdx);
888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ j(not_equal, miss);
889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the function.
891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount actual(argc);
892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(rdi, actual, JUMP_FUNCTION,
893257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), CALL_AS_METHOD);
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen// The generated code falls through if the call should be handled by runtime.
8983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallICBase::GenerateNormal(MacroAssembler* masm, int argc) {
899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
900402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rcx                    : function name
901402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[0]                 : return address
902402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[8]                 : argument argc
903402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[16]                : argument argc - 1
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ...
905402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[argc * 8]          : argument 1
906402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // rsp[(argc + 1) * 8]    : argument 0 = receiver
907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
9088defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Label miss;
909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver of the function from the stack.
911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9138defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateStringDictionaryReceiverCheck(masm, rdx, rax, rbx, &miss);
914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9158defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // rax: elements
9168defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Search the dictionary placing the result in rdi.
9178defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateDictionaryLoad(masm, &miss, rax, rcx, rbx, rdi, rdi);
918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9198defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateFunctionTailCall(masm, argc, &miss);
920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
9229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
9239dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
9249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
9253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallICBase::GenerateMiss(MacroAssembler* masm,
9263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              int argc,
9273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              IC::UtilityId id,
9283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Code::ExtraICState extra_state) {
9299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // ----------- S t a t e -------------
9309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rcx                      : function name
9319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rsp[0]                   : return address
9329dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rsp[8]                   : argument argc
9339dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rsp[16]                  : argument argc - 1
9349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // ...
9359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rsp[argc * 8]            : argument 1
9369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rsp[(argc + 1) * 8]      : argument 0 = receiver
9379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // -----------------------------------
9389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
93944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm->isolate()->counters();
9409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (id == IC::kCallIC_Miss) {
94144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ IncrementCounter(counters->call_miss(), 1);
9429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  } else {
94344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ IncrementCounter(counters->keyed_call_miss(), 1);
9449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
9459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
9469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Get the receiver of the function from the stack; 1 ~ return address.
9479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
9489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
9499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Enter an internal frame.
9503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
9513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
9529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
9533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Push the receiver and the name of the function.
9543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(rdx);
9553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(rcx);
9569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
9573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Call the entry.
9583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CEntryStub stub(1);
9593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Set(rax, 2);
9603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadAddress(rbx, ExternalReference(IC_Utility(id), masm->isolate()));
9613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallStub(&stub);
9629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
9633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Move result to rdi and exit the internal frame.
9643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movq(rdi, rax);
9653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
9669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
9679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Check if the receiver is a global object of some sort.
9689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // This can happen only for regular CallIC but not KeyedCallIC.
9699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (id == IC::kCallIC_Miss) {
9709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    Label invoke, global;
9719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));  // receiver
9729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ JumpIfSmi(rdx, &invoke);
9739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ CmpObjectType(rdx, JS_GLOBAL_OBJECT_TYPE, rcx);
9749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ j(equal, &global);
9759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ CmpInstanceType(rcx, JS_BUILTINS_OBJECT_TYPE);
9769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ j(not_equal, &invoke);
9779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
9789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Patch the receiver on the stack.
9799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ bind(&global);
9809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
9819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
9829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    __ bind(&invoke);
9839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  }
9849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
9859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Invoke the function.
9863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallKind call_kind = CallICBase::Contextual::decode(extra_state)
987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? CALL_AS_FUNCTION
988257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : CALL_AS_METHOD;
9899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  ParameterCount actual(argc);
990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(rdi,
991257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    actual,
992257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    JUMP_FUNCTION,
993257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(),
994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    call_kind);
9959dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
9969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
9979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
998257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid CallIC::GenerateMegamorphic(MacroAssembler* masm,
999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 int argc,
1000257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Code::ExtraICState extra_ic_state) {
10019dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // ----------- S t a t e -------------
10029dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rcx                      : function name
10039dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rsp[0]                   : return address
10049dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rsp[8]                   : argument argc
10059dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rsp[16]                  : argument argc - 1
10069dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // ...
10079dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rsp[argc * 8]            : argument 1
10089dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rsp[(argc + 1) * 8]      : argument 0 = receiver
10099dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // -----------------------------------
10109dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
10119dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Get the receiver of the function from the stack; 1 ~ return address.
10129dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1013257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC, extra_ic_state);
1014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateMiss(masm, argc, extra_ic_state);
10159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
10169dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
10179dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
10187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
10199dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // ----------- S t a t e -------------
10209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rcx                      : function name
10219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rsp[0]                   : return address
10229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rsp[8]                   : argument argc
10239dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rsp[16]                  : argument argc - 1
10249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // ...
10259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rsp[argc * 8]            : argument 1
10269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rsp[(argc + 1) * 8]      : argument 0 = receiver
10279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // -----------------------------------
10289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
10299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Get the receiver of the function from the stack; 1 ~ return address.
10309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
10319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
10320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label do_call, slow_call, slow_load;
10339dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  Label check_number_dictionary, check_string, lookup_monomorphic_cache;
10349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  Label index_smi, index_string;
10359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
10369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Check that the key is a smi.
10379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ JumpIfNotSmi(rcx, &check_string);
10389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
10399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ bind(&index_smi);
10409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Now the key is known to be a smi. This place is also jumped to from below
10419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // where a numeric string is converted to a smi.
10429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
10438defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateKeyedLoadReceiverCheck(
10448defd9ff6930b4e24729971a61cf7469daf119beSteve Block      masm, rdx, rax, Map::kHasIndexedInterceptor, &slow_call);
10459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
10469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateFastArrayLoad(
10479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      masm, rdx, rcx, rax, rbx, rdi, &check_number_dictionary, &slow_load);
104844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm->isolate()->counters();
104944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_call_generic_smi_fast(), 1);
10509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
10519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ bind(&do_call);
10529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // receiver in rdx is not used after this point.
10539dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rcx: key
10549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rdi: function
10558defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateFunctionTailCall(masm, argc, &slow_call);
10569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
10579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ bind(&check_number_dictionary);
105850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  // rax: elements
105950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  // rcx: smi key
10609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Check whether the elements is a number dictionary.
10619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
10629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                 Heap::kHashTableMapRootIndex);
10638defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ j(not_equal, &slow_load);
10649dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ SmiToInteger32(rbx, rcx);
10659dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // ebx: untagged index
10663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ LoadFromNumberDictionary(&slow_load, rax, rcx, rbx, r9, rdi, rdi);
106744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_call_generic_smi_dict(), 1);
10689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ jmp(&do_call);
10699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
10709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ bind(&slow_load);
10719dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // This branch is taken when calling KeyedCallIC_Miss is neither required
10729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // nor beneficial.
107344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_call_generic_slow_load(), 1);
10743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
10753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
10763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(rcx);  // save the key
10773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(rdx);  // pass the receiver
10783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(rcx);  // pass the key
10793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallRuntime(Runtime::kKeyedGetProperty, 2);
10803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ pop(rcx);  // restore the key
10813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
10829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ movq(rdi, rax);
10839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ jmp(&do_call);
10849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
10859dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ bind(&check_string);
10869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateKeyStringCheck(masm, rcx, rax, rbx, &index_string, &slow_call);
10879dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
10889dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // The key is known to be a symbol.
10899dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // If the receiver is a regular JS object with slow properties then do
10909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // a quick inline probe of the receiver's dictionary.
10919dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Otherwise do the monomorphic cache probe.
10928defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateKeyedLoadReceiverCheck(
10938defd9ff6930b4e24729971a61cf7469daf119beSteve Block      masm, rdx, rax, Map::kHasNamedInterceptor, &lookup_monomorphic_cache);
10949dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
10959dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ movq(rbx, FieldOperand(rdx, JSObject::kPropertiesOffset));
10969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
10979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                 Heap::kHashTableMapRootIndex);
10989dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ j(not_equal, &lookup_monomorphic_cache);
10999dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
11008defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateDictionaryLoad(masm, &slow_load, rbx, rcx, rax, rdi, rdi);
110144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_call_generic_lookup_dict(), 1);
11029dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ jmp(&do_call);
11039dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
11049dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ bind(&lookup_monomorphic_cache);
110544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1);
1106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateMonomorphicCacheProbe(masm,
1107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                argc,
1108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Code::KEYED_CALL_IC,
1109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                Code::kNoExtraICState);
11109dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Fall through on miss.
11119dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
11129dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ bind(&slow_call);
11139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // This branch is taken if:
11149dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // - the receiver requires boxing or access check,
11159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // - the key is neither smi nor symbol,
11169dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // - the value loaded is not a function,
11179dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // - there is hope that the runtime will create a monomorphic call stub
11189dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  //   that will get fetched next time.
111944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_call_generic_slow(), 1);
11209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateMiss(masm, argc);
11219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
11229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ bind(&index_string);
112380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ IndexFromHash(rbx, rcx);
11249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Now jump to the place where smi keys are handled.
11259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ jmp(&index_smi);
11267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
11277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) {
11309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // ----------- S t a t e -------------
11319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rcx                      : function name
11329dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rsp[0]                   : return address
11339dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rsp[8]                   : argument argc
11349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rsp[16]                  : argument argc - 1
11359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // ...
11369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rsp[argc * 8]            : argument 1
11379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // rsp[(argc + 1) * 8]      : argument 0 = receiver
11389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // -----------------------------------
11399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1140e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Check if the name is a string.
1141e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Label miss;
1142e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ JumpIfSmi(rcx, &miss);
1143e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Condition cond = masm->IsObjectStringType(rcx, rax, rax);
1144e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ j(NegateCondition(cond), &miss);
11453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallICBase::GenerateNormal(masm, argc);
1146e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&miss);
11479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  GenerateMiss(masm, argc);
11487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
11497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochstatic Operand GenerateMappedArgumentsLookup(MacroAssembler* masm,
11523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                             Register object,
11533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                             Register key,
11543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                             Register scratch1,
11553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                             Register scratch2,
11563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                             Register scratch3,
11573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                             Label* unmapped_case,
11583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                             Label* slow_case) {
11593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Heap* heap = masm->isolate()->heap();
11603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
11613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the receiver is a JSObject. Because of the elements
11623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // map check later, we do not need to check for interceptors or
11633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // whether it requires access checks.
11643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(object, slow_case);
11653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the object is some kind of JSObject.
11663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CmpObjectType(object, FIRST_JS_RECEIVER_TYPE, scratch1);
11673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(below, slow_case);
11683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
11693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check that the key is a positive smi.
11703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Condition check = masm->CheckNonNegativeSmi(key);
11713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(NegateCondition(check), slow_case);
11723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
11733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Load the elements into scratch1 and check its map. If not, jump
11743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // to the unmapped lookup with the parameter map in scratch1.
11753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Map> arguments_map(heap->non_strict_arguments_elements_map());
11763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ movq(scratch1, FieldOperand(object, JSObject::kElementsOffset));
11773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CheckMap(scratch1, arguments_map, slow_case, DONT_DO_SMI_CHECK);
11783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
11793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check if element is in the range of mapped arguments.
11803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ movq(scratch2, FieldOperand(scratch1, FixedArray::kLengthOffset));
11813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SmiSubConstant(scratch2, scratch2, Smi::FromInt(2));
11823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmpq(key, scratch2);
11833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(greater_equal, unmapped_case);
11843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
11853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Load element index and check whether it is the hole.
11863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int kHeaderSize = FixedArray::kHeaderSize + 2 * kPointerSize;
11873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SmiToInteger64(scratch3, key);
11883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ movq(scratch2, FieldOperand(scratch1,
11893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                 scratch3,
11903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                 times_pointer_size,
11913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                 kHeaderSize));
11923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CompareRoot(scratch2, Heap::kTheHoleValueRootIndex);
11933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(equal, unmapped_case);
11943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
11953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Load value from context and return it. We can reuse scratch1 because
11963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // we do not jump to the unmapped lookup (which requires the parameter
11973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // map in scratch1).
11983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ movq(scratch1, FieldOperand(scratch1, FixedArray::kHeaderSize));
11993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SmiToInteger64(scratch3, scratch2);
12003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return FieldOperand(scratch1,
12013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                      scratch3,
12023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                      times_pointer_size,
12033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                      Context::kHeaderSize);
12043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
12053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
12063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
12073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochstatic Operand GenerateUnmappedArgumentsLookup(MacroAssembler* masm,
12083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                               Register key,
12093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                               Register parameter_map,
12103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                               Register scratch,
12113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                               Label* slow_case) {
12123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Element is in arguments backing store, which is referenced by the
12133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // second element of the parameter_map. The parameter_map register
12143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // must be loaded with the parameter map of the arguments object and is
12153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // overwritten.
12163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize;
12173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Register backing_store = parameter_map;
12183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ movq(backing_store, FieldOperand(parameter_map, kBackingStoreOffset));
12193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Map> fixed_array_map(masm->isolate()->heap()->fixed_array_map());
12203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CheckMap(backing_store, fixed_array_map, slow_case, DONT_DO_SMI_CHECK);
12213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ movq(scratch, FieldOperand(backing_store, FixedArray::kLengthOffset));
12223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ cmpq(key, scratch);
12233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(greater_equal, slow_case);
12243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SmiToInteger64(scratch, key);
12253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return FieldOperand(backing_store,
12263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                      scratch,
12273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                      times_pointer_size,
12283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                      FixedArray::kHeaderSize);
12293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
12303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
12313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
12323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadIC::GenerateNonStrictArguments(MacroAssembler* masm) {
12333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ----------- S t a t e -------------
12343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rax    : key
12353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rdx    : receiver
12363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rsp[0]  : return address
12373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
12383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label slow, notin;
12393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Operand mapped_location =
12403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      GenerateMappedArgumentsLookup(
12413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          masm, rdx, rax, rbx, rcx, rdi, &notin, &slow);
12423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ movq(rax, mapped_location);
12433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Ret();
12443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&notin);
12453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // The unmapped lookup expects that the parameter map is in rbx.
12463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Operand unmapped_location =
12473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      GenerateUnmappedArgumentsLookup(masm, rax, rbx, rcx, &slow);
12483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CompareRoot(unmapped_location, Heap::kTheHoleValueRootIndex);
12493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(equal, &slow);
12503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ movq(rax, unmapped_location);
12513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Ret();
12523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&slow);
12533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  GenerateMiss(masm, false);
12543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
12553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
12563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
12573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedStoreIC::GenerateNonStrictArguments(MacroAssembler* masm) {
12583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ----------- S t a t e -------------
12593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rax     : value
12603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rcx     : key
12613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rdx     : receiver
12623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  -- rsp[0]  : return address
12633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
12643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label slow, notin;
12653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Operand mapped_location = GenerateMappedArgumentsLookup(
12663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm, rdx, rcx, rbx, rdi, r8, &notin, &slow);
12673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ movq(mapped_location, rax);
12683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ lea(r9, mapped_location);
12693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ movq(r8, rax);
12703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ RecordWrite(rbx,
12713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 r9,
12723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 r8,
12733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 kDontSaveFPRegs,
12743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 EMIT_REMEMBERED_SET,
12753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 INLINE_SMI_CHECK);
12763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Ret();
12773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&notin);
12783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // The unmapped lookup expects that the parameter map is in rbx.
12793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Operand unmapped_location =
12803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      GenerateUnmappedArgumentsLookup(masm, rcx, rbx, rdi, &slow);
12813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ movq(unmapped_location, rax);
12823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ lea(r9, unmapped_location);
12833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ movq(r8, rax);
12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ RecordWrite(rbx,
12853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 r9,
12863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 r8,
12873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 kDontSaveFPRegs,
12883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 EMIT_REMEMBERED_SET,
12893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 INLINE_SMI_CHECK);
12903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Ret();
12913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&slow);
12923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  GenerateMiss(masm, false);
12933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
12943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
12953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
12963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedCallIC::GenerateNonStrictArguments(MacroAssembler* masm,
12973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                             int argc) {
12983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ----------- S t a t e -------------
12993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rcx                      : function name
13003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rsp[0]                   : return address
13013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rsp[8]                   : argument argc
13023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rsp[16]                  : argument argc - 1
13033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // ...
13043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rsp[argc * 8]            : argument 1
13053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rsp[(argc + 1) * 8]      : argument 0 = receiver
13063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // -----------------------------------
13073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label slow, notin;
13083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
13093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Operand mapped_location = GenerateMappedArgumentsLookup(
13103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      masm, rdx, rcx, rbx, rax, r8, &notin, &slow);
13113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ movq(rdi, mapped_location);
13123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  GenerateFunctionTailCall(masm, argc, &slow);
13133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&notin);
13143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // The unmapped lookup expects that the parameter map is in rbx.
13153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Operand unmapped_location =
13163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      GenerateUnmappedArgumentsLookup(masm, rcx, rbx, rax, &slow);
13173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CompareRoot(unmapped_location, Heap::kTheHoleValueRootIndex);
13183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(equal, &slow);
13193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ movq(rdi, unmapped_location);
13203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  GenerateFunctionTailCall(masm, argc, &slow);
13213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&slow);
13223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  GenerateMiss(masm, argc);
13233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
13243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
13253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
13287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rax    : receiver
1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rcx    : name
1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0] : return address
1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Probe the stub cache.
1334589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, MONOMORPHIC);
133544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, rax, rcx, rbx,
133644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                  rdx);
1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Cache miss: Jump to runtime.
1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateNormal(MacroAssembler* masm) {
1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
13457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rax    : receiver
1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rcx    : name
1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0] : return address
1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
13498defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Label miss;
1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13518defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateStringDictionaryReceiverCheck(masm, rax, rdx, rbx, &miss);
1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13538defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //  rdx: elements
1354e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Search the dictionary placing the result in rax.
13558defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateDictionaryLoad(masm, &miss, rdx, rcx, rbx, rdi, rax);
1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ret(0);
1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Cache miss: Jump to runtime.
1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&miss);
1360402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  GenerateMiss(masm);
1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid LoadIC::GenerateMiss(MacroAssembler* masm) {
1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
13667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  //  -- rax    : receiver
1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rcx    : name
1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0] : return address
1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
137144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm->isolate()->counters();
137244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->load_miss(), 1);
13739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
13749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ pop(rbx);
13759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(rax);  // receiver
13769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(rcx);  // name
13779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(rbx);  // return address
13789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
13799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Perform tail call to the entry.
138044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference ref =
138144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate());
13829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ TailCallExternalReference(ref, 2, 1);
1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadIC::GenerateMiss(MacroAssembler* masm, bool force_generic) {
1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
13889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : key
13894515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- rdx    : receiver
13909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0]  : return address
1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
13924515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
139344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm->isolate()->counters();
139444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->keyed_load_miss(), 1);
13959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(rbx);
13974515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  __ push(rdx);  // receiver
13989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(rax);  // name
1399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(rbx);  // return address
1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform tail call to the entry.
1402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExternalReference ref = force_generic
1403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ? ExternalReference(IC_Utility(kKeyedLoadIC_MissForceGeneric),
1404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          masm->isolate())
1405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate());
14069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ TailCallExternalReference(ref, 2, 1);
14079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
14089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
14099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
14109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
14119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
14129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : key
14139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rdx    : receiver
14149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0]  : return address
14159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
14169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
14179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ pop(rbx);
14189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(rdx);  // receiver
14199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(rax);  // name
14209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(rbx);  // return address
14219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
14229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Perform tail call to the entry.
14239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid StoreIC::GenerateMegamorphic(MacroAssembler* masm,
1428e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                  StrictModeFlag strict_mode) {
1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rax    : value
1431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rcx    : name
14324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  //  -- rdx    : receiver
1433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- rsp[0] : return address
1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the receiver from the stack and probe the stub cache.
1437589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Code::Flags flags =
1438589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      Code::ComputeFlags(Code::STORE_IC, MONOMORPHIC, strict_mode);
143944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, rdx, rcx, rbx,
144044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                  no_reg);
1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Cache miss: Jump to runtime.
14434515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  GenerateMiss(masm);
1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid StoreIC::GenerateMiss(MacroAssembler* masm) {
14489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
14499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax    : value
14509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx    : name
14519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rdx    : receiver
14529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0] : return address
14539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
14549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
14559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ pop(rbx);
14569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(rdx);  // receiver
14579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(rcx);  // name
14589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(rax);  // value
14599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(rbx);  // return address
14609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
14619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Perform tail call to the entry.
146244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference ref =
146344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(IC_Utility(kStoreIC_Miss), masm->isolate());
14649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ TailCallExternalReference(ref, 3, 1);
14659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
14669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
14679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
14686ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid StoreIC::GenerateArrayLength(MacroAssembler* masm) {
14696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // ----------- S t a t e -------------
14706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rax    : value
14716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rcx    : name
14726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rdx    : receiver
14736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //  -- rsp[0] : return address
14746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // -----------------------------------
14756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  //
14763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // This accepts as a receiver anything JSArray::SetElementsLength accepts
14773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // (currently anything except for external arrays which means anything with
14783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // elements of FixedArray type).  Value must be a number, but only smis are
14793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // accepted as the most common case.
14806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Label miss;
14826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register receiver = rdx;
14846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register value = rax;
14856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Register scratch = rbx;
14866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the receiver isn't a smi.
14886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ JumpIfSmi(receiver, &miss);
14896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the object is a JS array.
14916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
14926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ j(not_equal, &miss);
14936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that elements are FixedArray.
1495756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // We rely on StoreIC_ArrayLength below to deal with all types of
1496756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // fast elements (including COW).
14976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ movq(scratch, FieldOperand(receiver, JSArray::kElementsOffset));
14986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch);
14996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ j(not_equal, &miss);
15006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that the array has fast properties, otherwise the length
15023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // property might have been redefined.
15033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movq(scratch, FieldOperand(receiver, JSArray::kPropertiesOffset));
15043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CompareRoot(FieldOperand(scratch, FixedArray::kMapOffset),
15053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 Heap::kHashTableMapRootIndex);
15063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(equal, &miss);
15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that value is a smi.
15096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ JumpIfNotSmi(value, &miss);
15106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Prepare tail call to StoreIC_ArrayLength.
15126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ pop(scratch);
15136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(receiver);
15146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(value);
15156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ push(scratch);  // return address
15166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
151744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference ref =
151844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference(IC_Utility(kStoreIC_ArrayLength), masm->isolate());
15196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ TailCallExternalReference(ref, 2, 1);
15206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ bind(&miss);
15226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  GenerateMiss(masm);
15246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
15256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15278defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid StoreIC::GenerateNormal(MacroAssembler* masm) {
15288defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // ----------- S t a t e -------------
15298defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //  -- rax    : value
15308defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //  -- rcx    : name
15318defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //  -- rdx    : receiver
15328defd9ff6930b4e24729971a61cf7469daf119beSteve Block  //  -- rsp[0] : return address
15338defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // -----------------------------------
15348defd9ff6930b4e24729971a61cf7469daf119beSteve Block
15350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label miss;
15368defd9ff6930b4e24729971a61cf7469daf119beSteve Block
15378defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateStringDictionaryReceiverCheck(masm, rdx, rbx, rdi, &miss);
15388defd9ff6930b4e24729971a61cf7469daf119beSteve Block
15398defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateDictionaryStore(masm, &miss, rbx, rcx, rax, r8, r9);
154044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm->isolate()->counters();
154144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->store_normal_hit(), 1);
15428defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ ret(0);
15438defd9ff6930b4e24729971a61cf7469daf119beSteve Block
15448defd9ff6930b4e24729971a61cf7469daf119beSteve Block  __ bind(&miss);
154544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->store_normal_miss(), 1);
15468defd9ff6930b4e24729971a61cf7469daf119beSteve Block  GenerateMiss(masm);
15478defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
15488defd9ff6930b4e24729971a61cf7469daf119beSteve Block
15498defd9ff6930b4e24729971a61cf7469daf119beSteve Block
1550e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid StoreIC::GenerateGlobalProxy(MacroAssembler* masm,
1551e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                  StrictModeFlag strict_mode) {
1552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // ----------- S t a t e -------------
1553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- rax    : value
1554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- rcx    : name
1555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- rdx    : receiver
1556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //  -- rsp[0] : return address
1557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // -----------------------------------
1558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ pop(rbx);
1559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ push(rdx);
1560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ push(rcx);
1561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ push(rax);
1562e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ Push(Smi::FromInt(NONE));  // PropertyAttributes
1563e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ Push(Smi::FromInt(strict_mode));
1564e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ push(rbx);  // return address
1565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Do tail-call to runtime routine.
1567e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
1568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1571e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
1572e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                              StrictModeFlag strict_mode) {
15739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
15749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax     : value
15759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx     : key
15769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rdx     : receiver
15779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0]  : return address
15789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
15799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
15809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ pop(rbx);
15819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(rdx);  // receiver
15829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(rcx);  // key
15839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(rax);  // value
1584e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ Push(Smi::FromInt(NONE));          // PropertyAttributes
1585e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ Push(Smi::FromInt(strict_mode));   // Strict mode.
15869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(rbx);  // return address
15879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
15889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Do tail-call to runtime routine.
1589e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
15909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
15919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
15929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
1593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedStoreIC::GenerateSlow(MacroAssembler* masm) {
15949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // ----------- S t a t e -------------
15959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rax     : value
15969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rcx     : key
15979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rdx     : receiver
15989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  //  -- rsp[0]  : return address
15999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // -----------------------------------
16009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
16019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ pop(rbx);
16029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(rdx);  // receiver
16039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(rcx);  // key
16049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(rax);  // value
16059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ push(rbx);  // return address
16069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
16079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  // Do tail-call to runtime routine.
1608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExternalReference ref(IC_Utility(kKeyedStoreIC_Slow), masm->isolate());
1609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ TailCallExternalReference(ref, 3, 1);
1610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedStoreIC::GenerateMiss(MacroAssembler* masm, bool force_generic) {
1614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
1615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rax     : value
1616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rcx     : key
1617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rdx     : receiver
1618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- rsp[0]  : return address
1619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
1620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1621257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ pop(rbx);
1622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ push(rdx);  // receiver
1623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ push(rcx);  // key
1624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ push(rax);  // value
1625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ push(rbx);  // return address
1626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1627257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Do tail-call to runtime routine.
1628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExternalReference ref = force_generic
1629257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ? ExternalReference(IC_Utility(kKeyedStoreIC_MissForceGeneric),
1630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        masm->isolate())
1631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    : ExternalReference(IC_Utility(kKeyedStoreIC_Miss), masm->isolate());
16329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  __ TailCallExternalReference(ref, 3, 1);
16339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
16349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
16359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
16363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid KeyedStoreIC::GenerateTransitionElementsSmiToDouble(MacroAssembler* masm) {
16373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ----------- S t a t e -------------
16383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //  -- rbx     : target map
16393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //  -- rdx     : receiver
16403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //  -- rsp[0]  : return address
16413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // -----------------------------------
16423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Must return the modified receiver in eax.
16433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!FLAG_trace_elements_transitions) {
16443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label fail;
16453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsTransitionGenerator::GenerateSmiOnlyToDouble(masm, &fail);
16463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movq(rax, rdx);
16473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Ret();
16483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&fail);
16493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
16503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ pop(rbx);
16523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(rdx);
16533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(rbx);  // return address
16543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ TailCallRuntime(Runtime::kTransitionElementsSmiToDouble, 1, 1);
16553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
16563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid KeyedStoreIC::GenerateTransitionElementsDoubleToObject(
16593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MacroAssembler* masm) {
16603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ----------- S t a t e -------------
16613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //  -- rbx     : target map
16623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //  -- rdx     : receiver
16633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //  -- rsp[0]  : return address
16643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // -----------------------------------
16653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Must return the modified receiver in eax.
16663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!FLAG_trace_elements_transitions) {
16673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label fail;
16683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsTransitionGenerator::GenerateDoubleToObject(masm, &fail);
16693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movq(rax, rdx);
16703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Ret();
16713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&fail);
16723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
16733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ pop(rbx);
16753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(rdx);
16763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(rbx);  // return address
16773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ TailCallRuntime(Runtime::kTransitionElementsDoubleToObject, 1, 1);
16783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
16793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __
1682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochCondition CompareIC::ComputeCondition(Token::Value op) {
1685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  switch (op) {
1686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::EQ_STRICT:
1687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::EQ:
1688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return equal;
1689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::LT:
1690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return less;
1691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::GT:
16923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return greater;
1693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::LTE:
16943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return less_equal;
1695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::GTE:
1696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return greater_equal;
1697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    default:
1698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      UNREACHABLE();
1699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return no_condition;
1700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
17041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockstatic bool HasInlinedSmiCode(Address address) {
17051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // The address of the instruction following the call.
17061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Address test_instruction_address =
17071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      address + Assembler::kCallTargetAddressOffset;
17081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // If the instruction following the call is not a test al, nothing
17101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // was inlined.
17111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return *test_instruction_address == Assembler::kTestAlByte;
17121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
17131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) {
1716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HandleScope scope;
1717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<Code> rewritten;
1718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  State previous_state = GetState();
17191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  State state = TargetState(previous_state, HasInlinedSmiCode(address()), x, y);
1721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (state == GENERIC) {
1722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompareStub stub(GetCondition(), strict(), NO_COMPARE_FLAGS);
1723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    rewritten = stub.GetCode();
1724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
1725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ICCompareStub stub(op_, state);
17263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (state == KNOWN_OBJECTS) {
17273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      stub.set_known_map(Handle<Map>(Handle<JSObject>::cast(x)->map()));
17283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    rewritten = stub.GetCode();
1730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  set_target(*rewritten);
1732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
1734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_ic) {
1735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF("[CompareIC (%s->%s)#%s]\n",
1736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           GetStateName(previous_state),
1737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           GetStateName(state),
1738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           Token::Name(op_));
1739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
17411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Activate inlined smi code.
17431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (previous_state == UNINITIALIZED) {
17441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    PatchInlinedSmiCode(address());
17451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid PatchInlinedSmiCode(Address address) {
17491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // The address of the instruction following the call.
17501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Address test_instruction_address =
17511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      address + Assembler::kCallTargetAddressOffset;
17521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // If the instruction following the call is not a test al, nothing
17541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // was inlined.
17551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (*test_instruction_address != Assembler::kTestAlByte) {
17561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(*test_instruction_address == Assembler::kNopByte);
17571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return;
17581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
17591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Address delta_address = test_instruction_address + 1;
17611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // The delta to the start of the map check instruction and the
17621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // condition code uses at the patched jump.
17631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int8_t delta = *reinterpret_cast<int8_t*>(delta_address);
17641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (FLAG_trace_ic) {
17651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    PrintF("[  patching ic at %p, test=%p, delta=%d\n",
17661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block           address, test_instruction_address, delta);
17671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
17681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Patch with a short conditional jump. There must be a
17701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // short jump-if-carry/not-carry at this position.
17711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Address jmp_address = test_instruction_address - delta;
17721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(*jmp_address == Assembler::kJncShortOpcode ||
17731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block         *jmp_address == Assembler::kJcShortOpcode);
17741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Condition cc = *jmp_address == Assembler::kJncShortOpcode
17751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      ? not_zero
17761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      : zero;
17771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc);
1778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
17809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
1781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
1782f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_X64
1784