ic-ia32.cc revision e0cee9b3ed82e2391fd85d118aeaa4ea361c687d
17f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Copyright 2010 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h" 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_IA32) 31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "codegen-inl.h" 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "ic-inl.h" 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "runtime.h" 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "stub-cache.h" 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); 538defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(equal, global_object, not_taken); 548defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ cmp(type, JS_BUILTINS_OBJECT_TYPE); 558defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(equal, global_object, not_taken); 568defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ cmp(type, JS_GLOBAL_PROXY_TYPE); 578defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(equal, global_object, not_taken); 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. 758defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ test(receiver, Immediate(kSmiTagMask)); 768defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(zero, miss, not_taken); 778defd9ff6930b4e24729971a61cf7469daf119beSteve Block 788defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Check that the receiver is a valid JS object. 798defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(r1, FieldOperand(receiver, HeapObject::kMapOffset)); 808defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ movzx_b(r0, FieldOperand(r1, Map::kInstanceTypeOffset)); 818defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ cmp(r0, FIRST_JS_OBJECT_TYPE); 828defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(below, miss, not_taken); 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 848defd9ff6930b4e24729971a61cf7469daf119beSteve Block // If this assert fails, we have to check upper bound too. 858defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 878defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateGlobalInstanceTypeCheck(masm, r0, miss); 888defd9ff6930b4e24729971a61cf7469daf119beSteve Block 898defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Check for non-global object that requires access check. 908defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ test_b(FieldOperand(r1, Map::kBitFieldOffset), 918defd9ff6930b4e24729971a61cf7469daf119beSteve Block (1 << Map::kIsAccessCheckNeeded) | 928defd9ff6930b4e24729971a61cf7469daf119beSteve Block (1 << Map::kHasNamedInterceptor)); 938defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(not_zero, miss, not_taken); 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 95402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(r0, FieldOperand(receiver, JSObject::kPropertiesOffset)); 968defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ CheckMap(r0, Factory::hash_table_map(), miss, true); 978defd9ff6930b4e24729971a61cf7469daf119beSteve Block} 98e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1008defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Probe the string dictionary in the |elements| register. Jump to the 1018defd9ff6930b4e24729971a61cf7469daf119beSteve Block// |done| label if a property with the given name is found leaving the 1028defd9ff6930b4e24729971a61cf7469daf119beSteve Block// index into the dictionary in |r0|. Jump to the |miss| label 1038defd9ff6930b4e24729971a61cf7469daf119beSteve Block// otherwise. 1048defd9ff6930b4e24729971a61cf7469daf119beSteve Blockstatic void GenerateStringDictionaryProbes(MacroAssembler* masm, 1058defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label* miss, 1068defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label* done, 1078defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register elements, 1088defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register name, 1098defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register r0, 1108defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register r1) { 111e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Assert that name contains a string. 112e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (FLAG_debug_code) __ AbortIfNotString(name); 113e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the capacity mask. 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kCapacityOffset = 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StringDictionary::kHeaderSize + 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StringDictionary::kCapacityIndex * kPointerSize; 1188defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(r1, FieldOperand(elements, kCapacityOffset)); 1198defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ shr(r1, kSmiTagSize); // convert smi to int 1208defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ dec(r1); 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Generate an unrolled loop that performs a few probes before 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // giving up. Measurements done on Gmail indicate that 2 probes 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // cover ~93% of loads from dictionaries. 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kProbes = 4; 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kElementsStartOffset = 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StringDictionary::kHeaderSize + 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StringDictionary::kElementsStartIndex * kPointerSize; 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < kProbes; i++) { 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the masked index: (hash + i + i * i) & mask. 1318defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(r0, FieldOperand(name, String::kHashFieldOffset)); 1328defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ shr(r0, String::kHashShift); 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (i > 0) { 1348defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ add(Operand(r0), Immediate(StringDictionary::GetProbeOffset(i))); 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1368defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ and_(r0, Operand(r1)); 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Scale the index by multiplying by the entry size. 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(StringDictionary::kEntrySize == 3); 1408defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ lea(r0, Operand(r0, r0, times_2, 0)); // r0 = r0 * 3 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the key is identical to the name. 1438defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ cmp(name, Operand(elements, r0, times_4, 1448defd9ff6930b4e24729971a61cf7469daf119beSteve Block kElementsStartOffset - kHeapObjectTag)); 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (i != kProbes - 1) { 1468defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(equal, done, taken); 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1488defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(not_equal, miss, not_taken); 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1518defd9ff6930b4e24729971a61cf7469daf119beSteve Block} 1528defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1538defd9ff6930b4e24729971a61cf7469daf119beSteve Block 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1558defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Helper function used to load a property from a dictionary backing 1568defd9ff6930b4e24729971a61cf7469daf119beSteve Block// storage. This function may fail to load a property even though it is 1578defd9ff6930b4e24729971a61cf7469daf119beSteve Block// in the dictionary, so code at miss_label must always call a backup 1588defd9ff6930b4e24729971a61cf7469daf119beSteve Block// property load that is complete. This function is safe to call if 1598defd9ff6930b4e24729971a61cf7469daf119beSteve Block// name is not a symbol, and will jump to the miss_label in that 1608defd9ff6930b4e24729971a61cf7469daf119beSteve Block// case. The generated code assumes that the receiver has slow 1618defd9ff6930b4e24729971a61cf7469daf119beSteve Block// properties, is not a global object and does not have interceptors. 1628defd9ff6930b4e24729971a61cf7469daf119beSteve Blockstatic void GenerateDictionaryLoad(MacroAssembler* masm, 1638defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label* miss_label, 1648defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register elements, 1658defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register name, 1668defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register r0, 1678defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register r1, 1688defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register result) { 1698defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Register use: 1708defd9ff6930b4e24729971a61cf7469daf119beSteve Block // 1718defd9ff6930b4e24729971a61cf7469daf119beSteve Block // elements - holds the property dictionary on entry and is unchanged. 1728defd9ff6930b4e24729971a61cf7469daf119beSteve Block // 1738defd9ff6930b4e24729971a61cf7469daf119beSteve Block // name - holds the name of the property on entry and is unchanged. 1748defd9ff6930b4e24729971a61cf7469daf119beSteve Block // 1758defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Scratch registers: 1768defd9ff6930b4e24729971a61cf7469daf119beSteve Block // 1778defd9ff6930b4e24729971a61cf7469daf119beSteve Block // r0 - used for the index into the property dictionary 1788defd9ff6930b4e24729971a61cf7469daf119beSteve Block // 1798defd9ff6930b4e24729971a61cf7469daf119beSteve Block // r1 - used to hold the capacity of the property dictionary. 1808defd9ff6930b4e24729971a61cf7469daf119beSteve Block // 1818defd9ff6930b4e24729971a61cf7469daf119beSteve Block // result - holds the result on exit. 1828defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1838defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label done; 1848defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1858defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Probe the dictionary. 1868defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateStringDictionaryProbes(masm, 1878defd9ff6930b4e24729971a61cf7469daf119beSteve Block miss_label, 1888defd9ff6930b4e24729971a61cf7469daf119beSteve Block &done, 1898defd9ff6930b4e24729971a61cf7469daf119beSteve Block elements, 1908defd9ff6930b4e24729971a61cf7469daf119beSteve Block name, 1918defd9ff6930b4e24729971a61cf7469daf119beSteve Block r0, 1928defd9ff6930b4e24729971a61cf7469daf119beSteve Block r1); 1938defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1948defd9ff6930b4e24729971a61cf7469daf119beSteve Block // If probing finds an entry in the dictionary, r0 contains the 1958defd9ff6930b4e24729971a61cf7469daf119beSteve Block // index into the dictionary. Check that the value is a normal 1968defd9ff6930b4e24729971a61cf7469daf119beSteve Block // property. 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&done); 1988defd9ff6930b4e24729971a61cf7469daf119beSteve Block const int kElementsStartOffset = 1998defd9ff6930b4e24729971a61cf7469daf119beSteve Block StringDictionary::kHeaderSize + 2008defd9ff6930b4e24729971a61cf7469daf119beSteve Block StringDictionary::kElementsStartIndex * kPointerSize; 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 2028defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag), 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, miss_label, not_taken); 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the value at the masked, scaled index. 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kValueOffset = kElementsStartOffset + kPointerSize; 2088defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(result, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag)); 2098defd9ff6930b4e24729971a61cf7469daf119beSteve Block} 2108defd9ff6930b4e24729971a61cf7469daf119beSteve Block 2118defd9ff6930b4e24729971a61cf7469daf119beSteve Block 2128defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Helper function used to store a property to a dictionary backing 2138defd9ff6930b4e24729971a61cf7469daf119beSteve Block// storage. This function may fail to store a property eventhough it 2148defd9ff6930b4e24729971a61cf7469daf119beSteve Block// is in the dictionary, so code at miss_label must always call a 2158defd9ff6930b4e24729971a61cf7469daf119beSteve Block// backup property store that is complete. This function is safe to 2168defd9ff6930b4e24729971a61cf7469daf119beSteve Block// call if name is not a symbol, and will jump to the miss_label in 2178defd9ff6930b4e24729971a61cf7469daf119beSteve Block// that case. The generated code assumes that the receiver has slow 2188defd9ff6930b4e24729971a61cf7469daf119beSteve Block// properties, is not a global object and does not have interceptors. 2198defd9ff6930b4e24729971a61cf7469daf119beSteve Blockstatic void GenerateDictionaryStore(MacroAssembler* masm, 2208defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label* miss_label, 2218defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register elements, 2228defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register name, 2238defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register value, 2248defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register r0, 2258defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register r1) { 2268defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Register use: 2278defd9ff6930b4e24729971a61cf7469daf119beSteve Block // 2288defd9ff6930b4e24729971a61cf7469daf119beSteve Block // elements - holds the property dictionary on entry and is clobbered. 2298defd9ff6930b4e24729971a61cf7469daf119beSteve Block // 2308defd9ff6930b4e24729971a61cf7469daf119beSteve Block // name - holds the name of the property on entry and is unchanged. 2318defd9ff6930b4e24729971a61cf7469daf119beSteve Block // 2328defd9ff6930b4e24729971a61cf7469daf119beSteve Block // value - holds the value to store and is unchanged. 2338defd9ff6930b4e24729971a61cf7469daf119beSteve Block // 2348defd9ff6930b4e24729971a61cf7469daf119beSteve Block // r0 - used for index into the property dictionary and is clobbered. 2358defd9ff6930b4e24729971a61cf7469daf119beSteve Block // 2368defd9ff6930b4e24729971a61cf7469daf119beSteve Block // r1 - used to hold the capacity of the property dictionary and is clobbered. 2378defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label done; 2388defd9ff6930b4e24729971a61cf7469daf119beSteve Block 2398defd9ff6930b4e24729971a61cf7469daf119beSteve Block 2408defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Probe the dictionary. 2418defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateStringDictionaryProbes(masm, 2428defd9ff6930b4e24729971a61cf7469daf119beSteve Block miss_label, 2438defd9ff6930b4e24729971a61cf7469daf119beSteve Block &done, 2448defd9ff6930b4e24729971a61cf7469daf119beSteve Block elements, 2458defd9ff6930b4e24729971a61cf7469daf119beSteve Block name, 2468defd9ff6930b4e24729971a61cf7469daf119beSteve Block r0, 2478defd9ff6930b4e24729971a61cf7469daf119beSteve Block r1); 2488defd9ff6930b4e24729971a61cf7469daf119beSteve Block 2498defd9ff6930b4e24729971a61cf7469daf119beSteve Block // If probing finds an entry in the dictionary, r0 contains the 2508defd9ff6930b4e24729971a61cf7469daf119beSteve Block // index into the dictionary. Check that the value is a normal 2518defd9ff6930b4e24729971a61cf7469daf119beSteve Block // property that is not read only. 2528defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ bind(&done); 2538defd9ff6930b4e24729971a61cf7469daf119beSteve Block const int kElementsStartOffset = 2548defd9ff6930b4e24729971a61cf7469daf119beSteve Block StringDictionary::kHeaderSize + 2558defd9ff6930b4e24729971a61cf7469daf119beSteve Block StringDictionary::kElementsStartIndex * kPointerSize; 2568defd9ff6930b4e24729971a61cf7469daf119beSteve Block const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 2578defd9ff6930b4e24729971a61cf7469daf119beSteve Block const int kTypeAndReadOnlyMask 2588defd9ff6930b4e24729971a61cf7469daf119beSteve Block = (PropertyDetails::TypeField::mask() | 2598defd9ff6930b4e24729971a61cf7469daf119beSteve Block PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize; 2608defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag), 2618defd9ff6930b4e24729971a61cf7469daf119beSteve Block Immediate(kTypeAndReadOnlyMask)); 2628defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(not_zero, miss_label, not_taken); 2638defd9ff6930b4e24729971a61cf7469daf119beSteve Block 2648defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Store the value at the masked, scaled index. 2658defd9ff6930b4e24729971a61cf7469daf119beSteve Block const int kValueOffset = kElementsStartOffset + kPointerSize; 2668defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ lea(r0, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag)); 2678defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(Operand(r0, 0), value); 2688defd9ff6930b4e24729971a61cf7469daf119beSteve Block 2698defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Update write barrier. Make sure not to clobber the value. 2708defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(r1, value); 2718defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ RecordWrite(elements, r0, r1); 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2756ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void GenerateNumberDictionaryLoad(MacroAssembler* masm, 2766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* miss, 2776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register elements, 2786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register key, 2796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register r0, 2806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register r1, 2817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register r2, 2827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result) { 2836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Register use: 2846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 2856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // elements - holds the slow-case elements of the receiver and is unchanged. 2866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 2877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // key - holds the smi key on entry and is unchanged. 2886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 2896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Scratch registers: 2906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 2916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // r0 - holds the untagged key on entry and holds the hash once computed. 2926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 2936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // r1 - used to hold the capacity mask of the dictionary 2946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 2956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // r2 - used for the index into the dictionary. 2967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // 2977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // result - holds the result on exit if the load succeeds and we fall through. 2987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label done; 3006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Compute the hash code from the untagged key. This must be kept in sync 3026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // with ComputeIntegerHash in utils.h. 3036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 3046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // hash = ~hash + (hash << 15); 3056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r1, r0); 3066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ not_(r0); 3076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ shl(r1, 15); 3086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ add(r0, Operand(r1)); 3096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // hash = hash ^ (hash >> 12); 3106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r1, r0); 3116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ shr(r1, 12); 3126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ xor_(r0, Operand(r1)); 3136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // hash = hash + (hash << 2); 3146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ lea(r0, Operand(r0, r0, times_4, 0)); 3156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // hash = hash ^ (hash >> 4); 3166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r1, r0); 3176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ shr(r1, 4); 3186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ xor_(r0, Operand(r1)); 3196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // hash = hash * 2057; 3206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ imul(r0, r0, 2057); 3216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // hash = hash ^ (hash >> 16); 3226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r1, r0); 3236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ shr(r1, 16); 3246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ xor_(r0, Operand(r1)); 3256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Compute capacity mask. 3276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r1, FieldOperand(elements, NumberDictionary::kCapacityOffset)); 3286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ shr(r1, kSmiTagSize); // convert smi to int 3296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ dec(r1); 3306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Generate an unrolled loop that performs a few probes before giving up. 3326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kProbes = 4; 3336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (int i = 0; i < kProbes; i++) { 3346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Use r2 for index calculations and keep the hash intact in r0. 3356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r2, r0); 3366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Compute the masked index: (hash + i + i * i) & mask. 3376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (i > 0) { 3386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ add(Operand(r2), Immediate(NumberDictionary::GetProbeOffset(i))); 3396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ and_(r2, Operand(r1)); 3416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Scale the index by multiplying by the entry size. 3436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(NumberDictionary::kEntrySize == 3); 3446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 3456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check if the key matches. 3476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(key, FieldOperand(elements, 3486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block r2, 3496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block times_pointer_size, 3506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NumberDictionary::kElementsStartOffset)); 3516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (i != (kProbes - 1)) { 3526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(equal, &done, taken); 3536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 3546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_equal, miss, not_taken); 3556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&done); 3596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the value is a normal propety. 3606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kDetailsOffset = 3616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NumberDictionary::kElementsStartOffset + 2 * kPointerSize; 3626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT_EQ(NORMAL, 0); 3636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), 3646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); 3656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_zero, miss); 3666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the value at the masked, scaled index. 3686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kValueOffset = 3696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NumberDictionary::kElementsStartOffset + kPointerSize; 3707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); 3716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 3726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The offset from the inlined patch site to the start of the 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// inlined load instruction. It is 7 bytes (test eax, imm) plus 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6 bytes (jne slow_label). 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int LoadIC::kOffsetToLoadInstruction = 13; 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateArrayLength(MacroAssembler* masm) { 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 382402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadArrayLength(masm, eax, edx, &miss); 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid LoadIC::GenerateStringLength(MacroAssembler* masm, 3951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool support_wrappers) { 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 397402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block StubCompiler::GenerateLoadStringLength(masm, eax, edx, ebx, &miss, 4041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block support_wrappers); 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) { 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 412402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadFunctionPrototype(masm, eax, edx, ebx, &miss); 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Checks the receiver for special cases (value type, slow case bits). 4257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Falls through for regular JS object. 4267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, 4277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register receiver, 4289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Register map, 4298defd9ff6930b4e24729971a61cf7469daf119beSteve Block int interceptor_bit, 4307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label* slow) { 4317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Register use: 4327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // receiver - holds the receiver and is unchanged. 4337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Scratch registers: 4349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // map - used to hold the map of the receiver. 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object isn't a smi. 4377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test(receiver, Immediate(kSmiTagMask)); 4387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(zero, slow, not_taken); 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the map of the receiver. 4419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ mov(map, FieldOperand(receiver, HeapObject::kMapOffset)); 442d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 443d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Check bit field. 4449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ test_b(FieldOperand(map, Map::kBitFieldOffset), 4458defd9ff6930b4e24729971a61cf7469daf119beSteve Block (1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit)); 4467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(not_zero, slow, not_taken); 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is some kind of JS object EXCEPT JS Value type. 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // In the case that the object is a value-wrapper object, 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // we enter the runtime system to make sure that indexing 4507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // into string objects works as intended. 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); 4527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 4539dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ CmpInstanceType(map, JS_OBJECT_TYPE); 4547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(below, slow, not_taken); 4557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 4567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 4577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 4587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Loads an indexed element from a fast case array. 459756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick// If not_fast_array is NULL, doesn't perform the elements map check. 4607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void GenerateFastArrayLoad(MacroAssembler* masm, 4617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register receiver, 4627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register key, 4637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch, 4647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result, 4657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label* not_fast_array, 4667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label* out_of_range) { 4677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Register use: 4687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // receiver - holds the receiver and is unchanged. 4697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // key - holds the key and is unchanged (must be a smi). 4707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Scratch registers: 4717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // scratch - used to hold elements of the receiver and the loaded value. 4727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // result - holds the result on exit if the load succeeds and 4737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // we fall through. 4747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 4757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(scratch, FieldOperand(receiver, JSObject::kElementsOffset)); 476756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (not_fast_array != NULL) { 477756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Check that the object is in fast mode and writable. 478756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ CheckMap(scratch, Factory::fixed_array_map(), not_fast_array, true); 479756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else { 480756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ AssertFastElements(scratch); 481756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the key (index) is within bounds. 4837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ cmp(key, FieldOperand(scratch, FixedArray::kLengthOffset)); 4847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(above_equal, out_of_range); 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fast case: Do the load. 4867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0)); 4877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(scratch, FieldOperand(scratch, key, times_2, FixedArray::kHeaderSize)); 4887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ cmp(Operand(scratch), Immediate(Factory::the_hole_value())); 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // In case the loaded value is the_hole we have to consult GetProperty 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to ensure the prototype chain is searched. 4917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(equal, out_of_range); 4927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (!result.is(scratch)) { 4937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(result, scratch); 4947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 4957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 4967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 4977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 4987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Checks whether a key is an array index string or a symbol string. 4999dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen// Falls through if the key is a symbol. 5007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void GenerateKeyStringCheck(MacroAssembler* masm, 5017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register key, 5027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register map, 5037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register hash, 5047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label* index_string, 5057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label* not_symbol) { 5067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Register use: 5077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // key - holds the key and is unchanged. Assumed to be non-smi. 5087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Scratch registers: 5097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // map - used to hold the map of the key. 5107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // hash - used to hold the hash of the key. 5117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ CmpObjectType(key, FIRST_NONSTRING_TYPE, map); 5127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(above_equal, not_symbol); 5137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 5147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Is the string an array index, with cached numeric value? 5157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(hash, FieldOperand(key, String::kHashFieldOffset)); 5167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test(hash, Immediate(String::kContainsCachedArrayIndexMask)); 5177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(zero, index_string, not_taken); 5187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 5197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Is the string a symbol? 5207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(kSymbolTag != 0); 5217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsSymbolMask); 5227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(zero, not_symbol, not_taken); 5237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 5247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 5257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 5267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 5277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------- S t a t e ------------- 5287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- eax : key 5297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- edx : receiver 5307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[0] : return address 5317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------------------------------- 532bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Label slow, check_string, index_smi, index_string, property_array_property; 5337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label check_pixel_array, probe_dictionary, check_number_dictionary; 5347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 5357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the key is a smi. 5367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test(eax, Immediate(kSmiTagMask)); 5377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(not_zero, &check_string, not_taken); 5387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_smi); 5397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Now the key is known to be a smi. This place is also jumped to from 5407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // where a numeric string is converted to a smi. 5417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 5428defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateKeyedLoadReceiverCheck( 5438defd9ff6930b4e24729971a61cf7469daf119beSteve Block masm, edx, ecx, Map::kHasIndexedInterceptor, &slow); 5448defd9ff6930b4e24729971a61cf7469daf119beSteve Block 545756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Check the "has fast elements" bit in the receiver's map which is 546756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // now in ecx. 547756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ test_b(FieldOperand(ecx, Map::kBitField2Offset), 548756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 1 << Map::kHasFastElements); 549756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ j(zero, &check_pixel_array, not_taken); 550756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 5517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateFastArrayLoad(masm, 5527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch edx, 5537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch eax, 5547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ecx, 5557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch eax, 556756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick NULL, 5577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &slow); 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); 559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&check_pixel_array); 5621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block GenerateFastPixelArrayLoad(masm, 5631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block edx, 5641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block eax, 5651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ecx, 5661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ebx, 5671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block eax, 5681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block &check_number_dictionary, 5691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block NULL, 5701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block &slow); 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&check_number_dictionary); 5736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check whether the elements is a number dictionary. 5746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver 5756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ebx: untagged index 5766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // eax: key 5776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: elements 5786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CheckMap(ecx, Factory::hash_table_map(), &slow, true); 5796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label slow_pop_receiver; 5806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Push receiver on the stack to free up a register for the dictionary 5816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // probing. 5826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(edx); 5836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GenerateNumberDictionaryLoad(masm, 5846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block &slow_pop_receiver, 5856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ecx, 5866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block eax, 5876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ebx, 5886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block edx, 5897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch edi, 5907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch eax); 5916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Pop receiver before returning. 5926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(edx); 5936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret(0); 5946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&slow_pop_receiver); 5966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Pop the receiver from the stack and jump to runtime. 5976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(edx); 5986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&slow); 600402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Slow case: jump to runtime. 601402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // edx: receiver 602402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // eax: key 603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); 604402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateRuntimeGetProperty(masm); 605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&check_string); 6077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateKeyStringCheck(masm, eax, ecx, ebx, &index_string, &slow); 608e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 6098defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateKeyedLoadReceiverCheck( 6108defd9ff6930b4e24729971a61cf7469daf119beSteve Block masm, edx, ecx, Map::kHasNamedInterceptor, &slow); 6118defd9ff6930b4e24729971a61cf7469daf119beSteve Block 612e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // If the receiver is a fast-case object, check the keyed lookup 613402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // cache. Otherwise probe the dictionary. 614402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset)); 615e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 616e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Immediate(Factory::hash_table_map())); 617e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, &probe_dictionary); 618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 619e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Load the map of the receiver, compute the keyed lookup cache hash 620e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // based on 32 bits of the map pointer and the string hash. 621402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); 622402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, ebx); 623402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ shr(ecx, KeyedLookupCache::kMapHashShift); 624402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(edi, FieldOperand(eax, String::kHashFieldOffset)); 625402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ shr(edi, String::kHashShift); 626402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ xor_(ecx, Operand(edi)); 627402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ and_(ecx, KeyedLookupCache::kCapacityMask); 628e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 629e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Load the key (consisting of map and symbol) from the cache and 630e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // check for match. 631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ExternalReference cache_keys 632e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke = ExternalReference::keyed_lookup_cache_keys(); 633402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(edi, ecx); 634e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ shl(edi, kPointerSizeLog2 + 1); 635e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys)); 636e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_equal, &slow); 637e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ add(Operand(edi), Immediate(kPointerSize)); 638402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(eax, Operand::StaticArray(edi, times_1, cache_keys)); 639e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_equal, &slow); 640e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 641bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Get field offset. 642402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // edx : receiver 643402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ebx : receiver's map 644402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // eax : key 645402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ecx : lookup cache index 646e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ExternalReference cache_field_offsets 647e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke = ExternalReference::keyed_lookup_cache_field_offsets(); 648402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(edi, 649402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Operand::StaticArray(ecx, times_pointer_size, cache_field_offsets)); 650402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(ecx, FieldOperand(ebx, Map::kInObjectPropertiesOffset)); 6517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ sub(edi, Operand(ecx)); 652bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ j(above_equal, &property_array_property); 653e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 654e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Load in-object property. 655402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset)); 656402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ add(ecx, Operand(edi)); 657402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, FieldOperand(edx, ecx, times_pointer_size, 0)); 6587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ IncrementCounter(&Counters::keyed_load_generic_lookup_cache, 1); 659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ret(0); 660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 661bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Load property array property. 662bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&property_array_property); 663bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ mov(eax, FieldOperand(edx, JSObject::kPropertiesOffset)); 664bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ mov(eax, FieldOperand(eax, edi, times_pointer_size, 665bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch FixedArray::kHeaderSize)); 666bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ IncrementCounter(&Counters::keyed_load_generic_lookup_cache, 1); 667bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ ret(0); 668bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 669e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Do a quick inline probe of the receiver's dictionary, if it 670e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // exists. 671e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&probe_dictionary); 6728defd9ff6930b4e24729971a61cf7469daf119beSteve Block 6738defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(ecx, FieldOperand(edx, JSObject::kMapOffset)); 6748defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 6758defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateGlobalInstanceTypeCheck(masm, ecx, &slow); 6768defd9ff6930b4e24729971a61cf7469daf119beSteve Block 6778defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateDictionaryLoad(masm, &slow, ebx, eax, ecx, edi, eax); 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 680e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&index_string); 68280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ IndexFromHash(ebx, eax); 6839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Now jump to the place where smi keys are handled. 6849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ jmp(&index_smi); 685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 688e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid KeyedLoadIC::GenerateString(MacroAssembler* masm) { 689e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------- S t a t e ------------- 6906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- eax : key (index) 691402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 692e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 693e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------------------------------- 6946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss; 6956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register receiver = edx; 6976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register index = eax; 6987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch1 = ebx; 6997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch2 = ecx; 7007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = eax; 7017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 7027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharAtGenerator char_at_generator(receiver, 7037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch index, 7047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch1, 7057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch2, 7067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch result, 7077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &miss, // When not a string. 7087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &miss, // When not a number. 7090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &miss, // When index out of range. 7107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch STRING_INDEX_IS_ARRAY_INDEX); 7117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch char_at_generator.GenerateFast(masm); 7127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ ret(0); 7137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch StubRuntimeCallHelper call_helper; 7157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch char_at_generator.GenerateSlow(masm, call_helper); 716e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 717e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&miss); 718e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke GenerateMiss(masm); 719e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 720e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 721e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 722402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { 723402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------- S t a t e ------------- 724402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 725402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 726402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- esp[0] : return address 727402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------------------------------- 728402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label slow; 729402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 730402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Check that the receiver isn't a smi. 731402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ test(edx, Immediate(kSmiTagMask)); 732402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ j(zero, &slow, not_taken); 733402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 734f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Check that the key is an array index, that is Uint32. 735f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ test(eax, Immediate(kSmiTagMask | kSmiSignMask)); 736402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ j(not_zero, &slow, not_taken); 737402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 738402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Get the map of the receiver. 739402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 740402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 741402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Check that it has indexed interceptor and access checks 742402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // are not enabled for this object. 743402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(ecx, FieldOperand(ecx, Map::kBitFieldOffset)); 744402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ and_(Operand(ecx), Immediate(kSlowCaseBitFieldMask)); 745402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(Operand(ecx), Immediate(1 << Map::kHasIndexedInterceptor)); 746402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ j(not_zero, &slow, not_taken); 747402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 748402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Everything is fine, call runtime. 749402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(ecx); 750402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(edx); // receiver 751402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(eax); // key 752402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(ecx); // return address 753402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 754402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Perform tail call to the entry. 7556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference ref = ExternalReference( 7566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block IC_Utility(kKeyedLoadPropertyWithInterceptor)); 7576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(ref, 2, 1); 758402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 759402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ bind(&slow); 760402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateMiss(masm); 7613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 7623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 764e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, 765e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch StrictModeFlag strict_mode) { 766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 7686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : key 7696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- edx : receiver 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label slow, fast, array, extra, check_pixel_array; 773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object isn't a smi. 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(edx, Immediate(kSmiTagMask)); 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &slow, not_taken); 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the map from the receiver. 7786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver does not require access checks. We need 780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to do this because this generic stub does not perform map checks. 7817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test_b(FieldOperand(edi, Map::kBitFieldOffset), 7827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1 << Map::kIsAccessCheckNeeded); 783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &slow, not_taken); 784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the key is a smi. 7856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(ecx, Immediate(kSmiTagMask)); 786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &slow, not_taken); 7876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CmpInstanceType(edi, JS_ARRAY_TYPE); 788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &array); 789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is some kind of JS object. 7906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE); 7916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(below, &slow, not_taken); 792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Object case: Check key against length in the elements array. 794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: value 795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edx: JSObject 7966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: key (a smi) 7976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 798756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Check that the object is in fast mode and writable. 7996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true); 8007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); 801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(below, &fast, taken); 802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Slow case: call runtime. 804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&slow); 805e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch GenerateRuntimeSetProperty(masm, strict_mode); 806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check whether the elements is a pixel array. 808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&check_pixel_array); 8096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // eax: value 8107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ecx: key (a smi) 8116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver 8126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edi: elements array 813e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch GenerateFastPixelArrayStore(masm, 814e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch edx, 815e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ecx, 816e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch eax, 817e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch edi, 818e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ebx, 819e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch false, 820e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch NULL, 821e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch &slow, 822e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch &slow, 823e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch &slow); 824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Extra capacity case: Check if there is extra capacity to 826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // perform the store and update the length. Used for adding one 827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // element to the array by writing to array[array.length]. 828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&extra); 829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: value 8306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver, a JSArray 8316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: key, a smi. 8326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edi: receiver->elements, a FixedArray 8336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // flags: compare (ecx, edx.length()) 834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &slow, not_taken); // do not leave holes in the array 8357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); 836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &slow, not_taken); 8376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Add 1 to receiver->length, and go to fast array write. 8386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ add(FieldOperand(edx, JSArray::kLengthOffset), 8397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Immediate(Smi::FromInt(1))); 840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&fast); 841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Array case: Get the length and the elements array from the JS 843756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // array. Check that the array is in fast mode (and writable); if it 844756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // is the length is always a smi. 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&array); 846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: value 8476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver, a JSArray 8486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: key, a smi. 8496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 8506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true); 851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the key against the length in the array, compute the 853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // address to store into and fall through to fast case. 8546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. 855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &extra, not_taken); 856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fast case: Do the store. 858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fast); 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: value 8606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: key (a smi) 8616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver 8626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edi: FixedArray receiver->elements 86325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ mov(CodeGenerator::FixedArrayElementOperand(edi, ecx), eax); 864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update write barrier for the elements array address. 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(eax)); 8666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ RecordWrite(edi, 0, edx, ecx); 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// The generated code does not accept smi keys. 8727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// The generated code falls through if both probes miss. 8737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void GenerateMonomorphicCacheProbe(MacroAssembler* masm, 8747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int argc, 8759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Code::Kind kind) { 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 877e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 8787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- edx : receiver 879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 8809dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Label number, non_number, non_string, boolean, probe, miss; 881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the stub cache. 883b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Code::Flags flags = Code::ComputeFlags(kind, 884b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch NOT_IN_LOOP, 885b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch MONOMORPHIC, 886b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Code::kNoExtraICState, 887b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch NORMAL, 888b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch argc); 889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, eax); 890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the stub cache probing failed, the receiver might be a value. 892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // For value objects, we use the map of the prototype objects for 893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the corresponding JSValue for the cache and that is what we need 894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to probe. 895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for number. 897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(edx, Immediate(kSmiTagMask)); 898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &number, not_taken); 899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ebx); 900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &non_number, taken); 901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&number); 902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadGlobalFunctionPrototype( 903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm, Context::NUMBER_FUNCTION_INDEX, edx); 904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&probe); 905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for string. 907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&non_number); 9087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ CmpInstanceType(ebx, FIRST_NONSTRING_TYPE); 909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &non_string, taken); 910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadGlobalFunctionPrototype( 911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm, Context::STRING_FUNCTION_INDEX, edx); 912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&probe); 913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for boolean. 915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&non_string); 916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(edx, Factory::true_value()); 917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &boolean, not_taken); 918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(edx, Factory::false_value()); 9199dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ j(not_equal, &miss, taken); 920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&boolean); 921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadGlobalFunctionPrototype( 922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm, Context::BOOLEAN_FUNCTION_INDEX, edx); 923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the stub cache for the value object. 925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&probe); 926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg); 9279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ bind(&miss); 928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9318defd9ff6930b4e24729971a61cf7469daf119beSteve Blockstatic void GenerateFunctionTailCall(MacroAssembler* masm, 9328defd9ff6930b4e24729971a61cf7469daf119beSteve Block int argc, 9338defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label* miss) { 934e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------- S t a t e ------------- 935e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 9368defd9ff6930b4e24729971a61cf7469daf119beSteve Block // -- edi : function 937e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 938e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 939e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 940e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 941e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------------------------------- 942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 943e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the result is not a smi. 944e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ test(edi, Immediate(kSmiTagMask)); 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, miss, not_taken); 946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 947e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the value is a JavaScript function, fetching its map into eax. 948e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax); 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, miss, not_taken); 950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the function. 952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount actual(argc); 953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeFunction(edi, actual, JUMP_FUNCTION); 954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen// The generated code falls through if the call should be handled by runtime. 9579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenstatic void GenerateCallNormal(MacroAssembler* masm, int argc) { 958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 959e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 960e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 961e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 962e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 963e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 9658defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label miss; 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver of the function from the stack; 1 ~ return address. 968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9708defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateStringDictionaryReceiverCheck(masm, edx, eax, ebx, &miss); 971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9728defd9ff6930b4e24729971a61cf7469daf119beSteve Block // eax: elements 9738defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Search the dictionary placing the result in edi. 9748defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateDictionaryLoad(masm, &miss, eax, ecx, edi, ebx, edi); 9758defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateFunctionTailCall(masm, argc, &miss); 9769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 9779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ bind(&miss); 978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 981b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochstatic void GenerateCallMiss(MacroAssembler* masm, 982b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int argc, 983b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch IC::UtilityId id) { 984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 985e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 986e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 987e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 988e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 989e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9928defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (id == IC::kCallIC_Miss) { 9938defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ IncrementCounter(&Counters::call_miss, 1); 9948defd9ff6930b4e24729971a61cf7469daf119beSteve Block } else { 9958defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ IncrementCounter(&Counters::keyed_call_miss, 1); 9968defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 9978defd9ff6930b4e24729971a61cf7469daf119beSteve Block 998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver of the function from the stack; 1 ~ return address. 999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Enter an internal frame. 1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ EnterInternalFrame(); 1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push the receiver and the name of the function. 1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(edx); 1006e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(ecx); 1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call the entry. 1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CEntryStub stub(1); 1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, Immediate(2)); 10117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(ebx, Immediate(ExternalReference(IC_Utility(id)))); 1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CallStub(&stub); 1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move result to edi and exit the internal frame. 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edi, eax); 1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LeaveInternalFrame(); 1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the receiver is a global object of some sort. 10198defd9ff6930b4e24729971a61cf7469daf119beSteve Block // This can happen only for regular CallIC but not KeyedCallIC. 10208defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (id == IC::kCallIC_Miss) { 10218defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label invoke, global; 10228defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); // receiver 10238defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ test(edx, Immediate(kSmiTagMask)); 10248defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(zero, &invoke, not_taken); 10258defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); 10268defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 10278defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ cmp(ebx, JS_GLOBAL_OBJECT_TYPE); 10288defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(equal, &global); 10298defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ cmp(ebx, JS_BUILTINS_OBJECT_TYPE); 10308defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(not_equal, &invoke); 10318defd9ff6930b4e24729971a61cf7469daf119beSteve Block 10328defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Patch the receiver on the stack. 10338defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ bind(&global); 10348defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 10358defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 10368defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ bind(&invoke); 10378defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the function. 1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount actual(argc); 1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeFunction(edi, actual, JUMP_FUNCTION); 1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { 10467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------- S t a t e ------------- 10477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ecx : name 10487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[0] : return address 10497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc - n) * 4] : arg[n] (zero-based) 10507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ... 10517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc + 1) * 4] : receiver 10527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------------------------------- 10537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 10547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Get the receiver of the function from the stack; 1 ~ return address. 10557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 10569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC); 10577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateMiss(masm, argc); 10587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 10597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 10607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 10617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid CallIC::GenerateNormal(MacroAssembler* masm, int argc) { 10629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // ----------- S t a t e ------------- 10639dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- ecx : name 10649dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- esp[0] : return address 10659dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- esp[(argc - n) * 4] : arg[n] (zero-based) 10669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- ... 10679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- esp[(argc + 1) * 4] : receiver 10689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // ----------------------------------- 10699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 10709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateCallNormal(masm, argc); 10717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateMiss(masm, argc); 10727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 10737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 10747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 10757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid CallIC::GenerateMiss(MacroAssembler* masm, int argc) { 10769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // ----------- S t a t e ------------- 10779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- ecx : name 10789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- esp[0] : return address 10799dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- esp[(argc - n) * 4] : arg[n] (zero-based) 10809dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- ... 10819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- esp[(argc + 1) * 4] : receiver 10829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // ----------------------------------- 10839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 10847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateCallMiss(masm, argc, IC::kCallIC_Miss); 10857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 10867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 10877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 10887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { 10897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------- S t a t e ------------- 10907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ecx : name 10917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[0] : return address 10927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc - n) * 4] : arg[n] (zero-based) 10937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ... 10947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc + 1) * 4] : receiver 10957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------------------------------- 10967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 10977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Get the receiver of the function from the stack; 1 ~ return address. 10987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 10997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label do_call, slow_call, slow_load, slow_reload_receiver; 11017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label check_number_dictionary, check_string, lookup_monomorphic_cache; 11027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_smi, index_string; 11037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the key is a smi. 11057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test(ecx, Immediate(kSmiTagMask)); 11067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(not_zero, &check_string, not_taken); 11077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_smi); 11097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Now the key is known to be a smi. This place is also jumped to from 11107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // where a numeric string is converted to a smi. 11117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11128defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateKeyedLoadReceiverCheck( 11138defd9ff6930b4e24729971a61cf7469daf119beSteve Block masm, edx, eax, Map::kHasIndexedInterceptor, &slow_call); 11147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateFastArrayLoad( 11169dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen masm, edx, ecx, eax, edi, &check_number_dictionary, &slow_load); 11177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ IncrementCounter(&Counters::keyed_call_generic_smi_fast, 1); 11187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&do_call); 11207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // receiver in edx is not used after this point. 11217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ecx: key 11227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // edi: function 11238defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateFunctionTailCall(masm, argc, &slow_call); 11247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&check_number_dictionary); 11267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // eax: elements 11277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ecx: smi key 11287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check whether the elements is a number dictionary. 11297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ CheckMap(eax, Factory::hash_table_map(), &slow_load, true); 11307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(ebx, ecx); 11317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ SmiUntag(ebx); 11327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ebx: untagged index 11337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Receiver in edx will be clobbered, need to reload it on miss. 11349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateNumberDictionaryLoad( 11359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen masm, &slow_reload_receiver, eax, ecx, ebx, edx, edi, edi); 11367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ IncrementCounter(&Counters::keyed_call_generic_smi_dict, 1); 11377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&do_call); 11387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&slow_reload_receiver); 11407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 11417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&slow_load); 11437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // This branch is taken when calling KeyedCallIC_Miss is neither required 11447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // nor beneficial. 11457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ IncrementCounter(&Counters::keyed_call_generic_slow_load, 1); 11467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ EnterInternalFrame(); 11477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(ecx); // save the key 11487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(edx); // pass the receiver 11497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(ecx); // pass the key 11507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ CallRuntime(Runtime::kKeyedGetProperty, 2); 11517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(ecx); // restore the key 11527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LeaveInternalFrame(); 11537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(edi, eax); 11547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&do_call); 11557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&check_string); 11577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateKeyStringCheck(masm, ecx, eax, ebx, &index_string, &slow_call); 11587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // The key is known to be a symbol. 11607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // If the receiver is a regular JS object with slow properties then do 11617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // a quick inline probe of the receiver's dictionary. 11627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Otherwise do the monomorphic cache probe. 11638defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateKeyedLoadReceiverCheck( 11648defd9ff6930b4e24729971a61cf7469daf119beSteve Block masm, edx, eax, Map::kHasNamedInterceptor, &lookup_monomorphic_cache); 11657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset)); 11678defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ CheckMap(ebx, Factory::hash_table_map(), &lookup_monomorphic_cache, true); 11687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11698defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateDictionaryLoad(masm, &slow_load, ebx, ecx, eax, edi, edi); 11707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ IncrementCounter(&Counters::keyed_call_generic_lookup_dict, 1); 11717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&do_call); 11727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&lookup_monomorphic_cache); 11747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ IncrementCounter(&Counters::keyed_call_generic_lookup_cache, 1); 11759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC); 11767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Fall through on miss. 11777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&slow_call); 11797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // This branch is taken if: 11807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // - the receiver requires boxing or access check, 11817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // - the key is neither smi nor symbol, 11827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // - the value loaded is not a function, 11837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // - there is hope that the runtime will create a monomorphic call stub 11847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // that will get fetched next time. 11857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ IncrementCounter(&Counters::keyed_call_generic_slow, 1); 11867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateMiss(masm, argc); 11877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_string); 118980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ IndexFromHash(ebx, ecx); 11909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Now jump to the place where smi keys are handled. 11919dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ jmp(&index_smi); 11927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 11937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { 11969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // ----------- S t a t e ------------- 11979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- ecx : name 11989dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- esp[0] : return address 11999dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- esp[(argc - n) * 4] : arg[n] (zero-based) 12009dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- ... 12019dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- esp[(argc + 1) * 4] : receiver 12029dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // ----------------------------------- 12039dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 1204e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Check if the name is a string. 1205e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Label miss; 1206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ test(ecx, Immediate(kSmiTagMask)); 1207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ j(zero, &miss); 1208e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Condition cond = masm->IsObjectStringType(ecx, eax, eax); 1209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ j(NegateCondition(cond), &miss); 12109dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateCallNormal(masm, argc); 1211e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&miss); 12127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateMiss(masm, argc); 12137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 12147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) { 12179dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // ----------- S t a t e ------------- 12189dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- ecx : name 12199dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- esp[0] : return address 12209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- esp[(argc - n) * 4] : arg[n] (zero-based) 12219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- ... 12229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- esp[(argc + 1) * 4] : receiver 12239dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // ----------------------------------- 12249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 12257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss); 12267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 12277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateMegamorphic(MacroAssembler* masm) { 1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1231402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the stub cache. 1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, 1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NOT_IN_LOOP, 1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MONOMORPHIC); 1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCache::GenerateProbe(masm, flags, eax, ecx, ebx, edx); 1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cache miss: Jump to runtime. 1243402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateMiss(masm); 1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateNormal(MacroAssembler* masm) { 1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1249402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 12538defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label miss; 1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12558defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateStringDictionaryReceiverCheck(masm, eax, edx, ebx, &miss); 1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12578defd9ff6930b4e24729971a61cf7469daf119beSteve Block // edx: elements 1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Search the dictionary placing the result in eax. 12598defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateDictionaryLoad(masm, &miss, edx, ecx, edi, ebx, eax); 1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Cache miss: Jump to runtime. 1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 1264402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateMiss(masm); 1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateMiss(MacroAssembler* masm) { 1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1270402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12758defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ IncrementCounter(&Counters::load_miss, 1); 12768defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); 1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(eax); // receiver 1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); // name 1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); // return address 1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform tail call to the entry. 12836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss)); 12846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(ref, 2, 1); 1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { 1289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (V8::UseCrankshaft()) return false; 1290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The address of the instruction following the call. 1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address test_instruction_address = 1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block address + Assembler::kCallTargetAddressOffset; 1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the instruction following the call is not a test eax, nothing 1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // was inlined. 1296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (*test_instruction_address != Assembler::kTestEaxByte) return false; 1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address delta_address = test_instruction_address + 1; 1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The delta to the start of the map check instruction. 1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int delta = *reinterpret_cast<int*>(delta_address); 1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The map address is the last 4 bytes of the 7-byte 1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // operand-immediate compare instruction, so we add 3 to get the 1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // offset to the last 4 bytes. 1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address map_address = test_instruction_address + delta + 3; 1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *(reinterpret_cast<Object**>(map_address)) = map; 1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The offset is in the last 4 bytes of a six byte 1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // memory-to-register move instruction, so we add 2 to get the 1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // offset to the last 4 bytes. 1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address offset_address = 1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block test_instruction_address + delta + kOffsetToLoadInstruction + 2; 1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; 1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen// One byte opcode for mov ecx,0xXXXXXXXX. 1319f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch// Marks inlined contextual loads using all kinds of cells. Generated 1320f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch// code has the hole check: 1321f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch// mov reg, <cell> 1322f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch// mov reg, (<cell>, value offset) 1323f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch// cmp reg, <the hole> 1324f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch// je slow 1325f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch// ;; use reg 13260d5e116f6aee03185f237311a943491bb079a768Kristian Monsenstatic const byte kMovEcxByte = 0xB9; 13270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 1328f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch// One byte opcode for mov edx,0xXXXXXXXX. 1329f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch// Marks inlined contextual loads using only "don't delete" 1330f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch// cells. Generated code doesn't have the hole check: 1331f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch// mov reg, <cell> 1332f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch// mov reg, (<cell>, value offset) 1333f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch// ;; use reg 1334f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochstatic const byte kMovEdxByte = 0xBA; 1335f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 13360d5e116f6aee03185f237311a943491bb079a768Kristian Monsenbool LoadIC::PatchInlinedContextualLoad(Address address, 13370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Object* map, 1338f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Object* cell, 1339f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch bool is_dont_delete) { 1340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (V8::UseCrankshaft()) return false; 1341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 13420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // The address of the instruction following the call. 13430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Address mov_instruction_address = 13440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen address + Assembler::kCallTargetAddressOffset; 1345f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // If the instruction following the call is not a mov ecx/edx, 1346f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // nothing was inlined. 1347f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch byte b = *mov_instruction_address; 1348f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if (b != kMovEcxByte && b != kMovEdxByte) return false; 1349f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // If we don't have the hole check generated, we can only support 1350f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // "don't delete" cells. 1351f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if (b == kMovEdxByte && !is_dont_delete) return false; 13520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 13530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Address delta_address = mov_instruction_address + 1; 13540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // The delta to the start of the map check instruction. 13550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int delta = *reinterpret_cast<int*>(delta_address); 13560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 13570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // The map address is the last 4 bytes of the 7-byte 13580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // operand-immediate compare instruction, so we add 3 to get the 13590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // offset to the last 4 bytes. 13600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Address map_address = mov_instruction_address + delta + 3; 13610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen *(reinterpret_cast<Object**>(map_address)) = map; 13620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 13630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // The cell is in the last 4 bytes of a five byte mov reg, imm32 13640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // instruction, so we add 1 to get the offset to the last 4 bytes. 13650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Address offset_address = 13660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen mov_instruction_address + delta + kOffsetToLoadInstruction + 1; 13670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen *reinterpret_cast<Object**>(offset_address) = cell; 13680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen return true; 13690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 13700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 13710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 137250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsenbool StoreIC::PatchInlinedStore(Address address, Object* map, int offset) { 1373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (V8::UseCrankshaft()) return false; 1374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 137550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // The address of the instruction following the call. 137650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen Address test_instruction_address = 137750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen address + Assembler::kCallTargetAddressOffset; 137850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 137950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // If the instruction following the call is not a test eax, nothing 138050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // was inlined. 1381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (*test_instruction_address != Assembler::kTestEaxByte) return false; 138250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 138350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // Extract the encoded deltas from the test eax instruction. 138450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen Address encoded_offsets_address = test_instruction_address + 1; 138550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen int encoded_offsets = *reinterpret_cast<int*>(encoded_offsets_address); 138650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen int delta_to_map_check = -(encoded_offsets & 0xFFFF); 138750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen int delta_to_record_write = encoded_offsets >> 16; 138850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 138950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // Patch the map to check. The map address is the last 4 bytes of 139050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // the 7-byte operand-immediate compare instruction. 139150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen Address map_check_address = test_instruction_address + delta_to_map_check; 139250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen Address map_address = map_check_address + 3; 139350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen *(reinterpret_cast<Object**>(map_address)) = map; 139450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 139550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // Patch the offset in the store instruction. The offset is in the 139650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // last 4 bytes of a six byte register-to-memory move instruction. 139750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen Address offset_address = 139850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen map_check_address + StoreIC::kOffsetToStoreInstruction + 2; 139950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // The offset should have initial value (kMaxInt - 1), cleared value 140050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // (-1) or we should be clearing the inlined version. 140150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt - 1 || 140250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen *reinterpret_cast<int*>(offset_address) == -1 || 140350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen (offset == 0 && map == Heap::null_value())); 140450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; 140550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 140650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // Patch the offset in the write-barrier code. The offset is the 140750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // last 4 bytes of a six byte lea instruction. 140850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen offset_address = map_check_address + delta_to_record_write + 2; 140950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // The offset should have initial value (kMaxInt), cleared value 141050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // (-1) or we should be clearing the inlined version. 141150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt || 141250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen *reinterpret_cast<int*>(offset_address) == -1 || 141350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen (offset == 0 && map == Heap::null_value())); 141450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; 141550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 141650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen return true; 141750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen} 141850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 141950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool PatchInlinedMapCheck(Address address, Object* map) { 1421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (V8::UseCrankshaft()) return false; 1422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address test_instruction_address = 1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block address + Assembler::kCallTargetAddressOffset; 1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The keyed load has a fast inlined case if the IC call instruction 1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is immediately followed by a test instruction. 1427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (*test_instruction_address != Assembler::kTestEaxByte) return false; 1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fetch the offset from the test instruction to the map cmp 1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // instruction. This offset is stored in the last 4 bytes of the 5 1431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // byte test instruction. 1432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address delta_address = test_instruction_address + 1; 1433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int delta = *reinterpret_cast<int*>(delta_address); 1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the map address. The map address is in the last 4 bytes 1435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // of the 7-byte operand-immediate compare instruction, so we add 3 1436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to the offset to get the map address. 1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address map_address = test_instruction_address + delta + 3; 1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the map check. 1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *(reinterpret_cast<Object**>(map_address)) = map; 1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool KeyedLoadIC::PatchInlinedLoad(Address address, Object* map) { 1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return PatchInlinedMapCheck(address, map); 1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool KeyedStoreIC::PatchInlinedStore(Address address, Object* map) { 1450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return PatchInlinedMapCheck(address, map); 1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { 1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1456402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 1457402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14618defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ IncrementCounter(&Counters::keyed_load_miss, 1); 14628defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1463402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(ebx); 1464402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(edx); // receiver 1465402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(eax); // name 1466402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(ebx); // return address 1467402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1468402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Perform tail call to the entry. 14696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss)); 14706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(ref, 2, 1); 1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1474402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { 1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1476402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 1477402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); 1482402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(edx); // receiver 1483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(eax); // name 1484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); // return address 1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform tail call to the entry. 14876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid StoreIC::GenerateMegamorphic(MacroAssembler* masm, 1492e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch StrictModeFlag strict_mode) { 1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 14964515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- edx : receiver 1497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, 1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NOT_IN_LOOP, 15021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block MONOMORPHIC, 1503e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch strict_mode); 1504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg); 1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cache miss: Jump to runtime. 15074515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke GenerateMiss(masm); 1508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid StoreIC::GenerateMiss(MacroAssembler* masm) { 1512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 15154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- edx : receiver 1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); 15204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(edx); 1521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); 1522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(eax); 1523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); 1524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform tail call to the entry. 15266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_Miss)); 15276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(ref, 3, 1); 15286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 15296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 153150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen// The offset from the inlined patch site to the start of the inlined 153250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen// store instruction. It is 7 bytes (test reg, imm) plus 6 bytes (jne 153350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen// slow_label). 153450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsenconst int StoreIC::kOffsetToStoreInstruction = 13; 153550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 153650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 15376ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid StoreIC::GenerateArrayLength(MacroAssembler* masm) { 15386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 15396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- eax : value 15406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : name 15416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- edx : receiver 15426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[0] : return address 15436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 15446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 15456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // This accepts as a receiver anything JSObject::SetElementsLength accepts 15466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // (currently anything except for external and pixel arrays which means 15476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // anything with elements of FixedArray type.), but currently is restricted 15486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // to JSArray. 15496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Value must be a number, but only smis are accepted as the most common case. 15506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss; 15526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register receiver = edx; 15546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register value = eax; 15556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch = ebx; 15566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the receiver isn't a smi. 15586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(receiver, Immediate(kSmiTagMask)); 15596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(zero, &miss, not_taken); 15606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the object is a JS array. 15626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); 15636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_equal, &miss, not_taken); 15646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that elements are FixedArray. 1566756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // We rely on StoreIC_ArrayLength below to deal with all types of 1567756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // fast elements (including COW). 15686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(scratch, FieldOperand(receiver, JSArray::kElementsOffset)); 15696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch); 15706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_equal, &miss, not_taken); 15716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that value is a smi. 15736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(value, Immediate(kSmiTagMask)); 15746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_zero, &miss, not_taken); 15756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Prepare tail call to StoreIC_ArrayLength. 15776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(scratch); 15786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(receiver); 15796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(value); 15806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(scratch); // return address 15816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_ArrayLength)); 15836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(ref, 2, 1); 15846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss); 15866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GenerateMiss(masm); 1588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15918defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid StoreIC::GenerateNormal(MacroAssembler* masm) { 15928defd9ff6930b4e24729971a61cf7469daf119beSteve Block // ----------- S t a t e ------------- 15938defd9ff6930b4e24729971a61cf7469daf119beSteve Block // -- eax : value 15948defd9ff6930b4e24729971a61cf7469daf119beSteve Block // -- ecx : name 15958defd9ff6930b4e24729971a61cf7469daf119beSteve Block // -- edx : receiver 15968defd9ff6930b4e24729971a61cf7469daf119beSteve Block // -- esp[0] : return address 15978defd9ff6930b4e24729971a61cf7469daf119beSteve Block // ----------------------------------- 15988defd9ff6930b4e24729971a61cf7469daf119beSteve Block 15998defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label miss, restore_miss; 16008defd9ff6930b4e24729971a61cf7469daf119beSteve Block 16018defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateStringDictionaryReceiverCheck(masm, edx, ebx, edi, &miss); 16028defd9ff6930b4e24729971a61cf7469daf119beSteve Block 16038defd9ff6930b4e24729971a61cf7469daf119beSteve Block // A lot of registers are needed for storing to slow case 16048defd9ff6930b4e24729971a61cf7469daf119beSteve Block // objects. Push and restore receiver but rely on 16058defd9ff6930b4e24729971a61cf7469daf119beSteve Block // GenerateDictionaryStore preserving the value and name. 16068defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ push(edx); 16078defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateDictionaryStore(masm, &restore_miss, ebx, ecx, eax, edx, edi); 16088defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ Drop(1); 16098defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ IncrementCounter(&Counters::store_normal_hit, 1); 16108defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ ret(0); 16118defd9ff6930b4e24729971a61cf7469daf119beSteve Block 16128defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ bind(&restore_miss); 16138defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ pop(edx); 16148defd9ff6930b4e24729971a61cf7469daf119beSteve Block 16158defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ bind(&miss); 16168defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ IncrementCounter(&Counters::store_normal_miss, 1); 16178defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateMiss(masm); 16188defd9ff6930b4e24729971a61cf7469daf119beSteve Block} 16198defd9ff6930b4e24729971a61cf7469daf119beSteve Block 16208defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1621e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid StoreIC::GenerateGlobalProxy(MacroAssembler* masm, 1622e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch StrictModeFlag strict_mode) { 1623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------- S t a t e ------------- 1624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- eax : value 1625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- ecx : name 1626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- edx : receiver 1627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- esp[0] : return address 1628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------------------------------- 1629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ pop(ebx); 1630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(edx); 1631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(ecx); 1632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(eax); 1633e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(Immediate(Smi::FromInt(NONE))); // PropertyAttributes 1634e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(Immediate(Smi::FromInt(strict_mode))); 1635e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(ebx); // return address 1636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Do tail-call to runtime routine. 1638e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ TailCallRuntime(Runtime::kSetProperty, 5, 1); 1639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1642e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm, 1643e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch StrictModeFlag strict_mode) { 1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 16466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : key 16476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- edx : receiver 1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(ebx); 16526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(edx); 1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); 16546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(eax); 1655e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(Immediate(Smi::FromInt(NONE))); // PropertyAttributes 1656e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(Immediate(Smi::FromInt(strict_mode))); // Strict mode. 1657e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(ebx); // return address 1658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to runtime routine. 1660e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ TailCallRuntime(Runtime::kSetProperty, 5, 1); 1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1664402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { 1665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 16676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : key 16686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- edx : receiver 1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(ebx); 16736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(edx); 1674402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(ecx); 16756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(eax); 16766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(ebx); 1677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to runtime routine. 16796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); 16806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(ref, 3, 1); 1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 1685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochCondition CompareIC::ComputeCondition(Token::Value op) { 1688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (op) { 1689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::EQ_STRICT: 1690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::EQ: 1691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return equal; 1692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::LT: 1693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return less; 1694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::GT: 1695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Reverse left and right operands to obtain ECMA-262 conversion order. 1696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return less; 1697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::LTE: 1698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Reverse left and right operands to obtain ECMA-262 conversion order. 1699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return greater_equal; 1700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::GTE: 1701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return greater_equal; 1702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch default: 1703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UNREACHABLE(); 1704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return no_condition; 1705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic bool HasInlinedSmiCode(Address address) { 1710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The address of the instruction following the call. 1711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Address test_instruction_address = 1712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch address + Assembler::kCallTargetAddressOffset; 1713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If the instruction following the call is not a test al, nothing 1715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // was inlined. 1716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return *test_instruction_address == Assembler::kTestAlByte; 1717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { 1721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HandleScope scope; 1722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Code> rewritten; 1723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch State previous_state = GetState(); 1724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch State state = TargetState(previous_state, HasInlinedSmiCode(address()), x, y); 1726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (state == GENERIC) { 1727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CompareStub stub(GetCondition(), strict(), NO_COMPARE_FLAGS); 1728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch rewritten = stub.GetCode(); 1729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ICCompareStub stub(op_, state); 1731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch rewritten = stub.GetCode(); 1732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch set_target(*rewritten); 1734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG 1736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_ic) { 1737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("[CompareIC (%s->%s)#%s]\n", 1738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch GetStateName(previous_state), 1739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch GetStateName(state), 1740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Token::Name(op_)); 1741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif 1743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Activate inlined smi code. 1745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (previous_state == UNINITIALIZED) { 1746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PatchInlinedSmiCode(address()); 1747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid PatchInlinedSmiCode(Address address) { 1752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The address of the instruction following the call. 1753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Address test_instruction_address = 1754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch address + Assembler::kCallTargetAddressOffset; 1755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If the instruction following the call is not a test al, nothing 1757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // was inlined. 1758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (*test_instruction_address != Assembler::kTestAlByte) { 1759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(*test_instruction_address == Assembler::kNopByte); 1760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 1761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Address delta_address = test_instruction_address + 1; 1764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The delta to the start of the map check instruction and the 1765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // condition code uses at the patched jump. 1766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int8_t delta = *reinterpret_cast<int8_t*>(delta_address); 1767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_ic) { 1768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("[ patching ic at %p, test=%p, delta=%d\n", 1769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch address, test_instruction_address, delta); 1770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Patch with a short conditional jump. There must be a 1773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // short jump-if-carry/not-carry at this position. 1774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Address jmp_address = test_instruction_address - delta; 1775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(*jmp_address == Assembler::kJncShortOpcode || 1776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch *jmp_address == Assembler::kJcShortOpcode); 1777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Condition cc = *jmp_address == Assembler::kJncShortOpcode 1778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ? not_zero 1779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : zero; 1780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); 1781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 1785f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1786f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_IA32 1787