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