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, ¬in, &slow); 12423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movq(rax, mapped_location); 12433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Ret(); 12443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(¬in); 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, ¬in, &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(¬in); 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, ¬in, &slow); 13113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movq(rdi, mapped_location); 13123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch GenerateFunctionTailCall(masm, argc, &slow); 13133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(¬in); 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