ic-ia32.cc revision bb769b257e753aafcbd96767abb2abc645eaa20c
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" 36d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "utils.h" 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ---------------------------------------------------------------------------- 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Static IC stub generators. 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm) 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 488defd9ff6930b4e24729971a61cf7469daf119beSteve Blockstatic void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, 498defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register type, 508defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label* global_object) { 518defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Register usage: 528defd9ff6930b4e24729971a61cf7469daf119beSteve Block // type: holds the receiver instance type on entry. 538defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ cmp(type, JS_GLOBAL_OBJECT_TYPE); 548defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(equal, global_object, not_taken); 558defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ cmp(type, JS_BUILTINS_OBJECT_TYPE); 568defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(equal, global_object, not_taken); 578defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ cmp(type, JS_GLOBAL_PROXY_TYPE); 588defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(equal, global_object, not_taken); 598defd9ff6930b4e24729971a61cf7469daf119beSteve Block} 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 628defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Generated code falls through if the receiver is a regular non-global 638defd9ff6930b4e24729971a61cf7469daf119beSteve Block// JS object with slow properties and no interceptors. 648defd9ff6930b4e24729971a61cf7469daf119beSteve Blockstatic void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm, 658defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register receiver, 668defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register r0, 678defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register r1, 688defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label* miss) { 698defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Register usage: 708defd9ff6930b4e24729971a61cf7469daf119beSteve Block // receiver: holds the receiver on entry and is unchanged. 718defd9ff6930b4e24729971a61cf7469daf119beSteve Block // r0: used to hold receiver instance type. 728defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Holds the property dictionary on fall through. 738defd9ff6930b4e24729971a61cf7469daf119beSteve Block // r1: used to hold receivers map. 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 758defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Check that the receiver isn't a smi. 768defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ test(receiver, Immediate(kSmiTagMask)); 778defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(zero, miss, not_taken); 788defd9ff6930b4e24729971a61cf7469daf119beSteve Block 798defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Check that the receiver is a valid JS object. 808defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(r1, FieldOperand(receiver, HeapObject::kMapOffset)); 818defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ movzx_b(r0, FieldOperand(r1, Map::kInstanceTypeOffset)); 828defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ cmp(r0, FIRST_JS_OBJECT_TYPE); 838defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(below, miss, not_taken); 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 858defd9ff6930b4e24729971a61cf7469daf119beSteve Block // If this assert fails, we have to check upper bound too. 868defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 888defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateGlobalInstanceTypeCheck(masm, r0, miss); 898defd9ff6930b4e24729971a61cf7469daf119beSteve Block 908defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Check for non-global object that requires access check. 918defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ test_b(FieldOperand(r1, Map::kBitFieldOffset), 928defd9ff6930b4e24729971a61cf7469daf119beSteve Block (1 << Map::kIsAccessCheckNeeded) | 938defd9ff6930b4e24729971a61cf7469daf119beSteve Block (1 << Map::kHasNamedInterceptor)); 948defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(not_zero, miss, not_taken); 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 96402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(r0, FieldOperand(receiver, JSObject::kPropertiesOffset)); 978defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ CheckMap(r0, Factory::hash_table_map(), miss, true); 988defd9ff6930b4e24729971a61cf7469daf119beSteve Block} 99e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1018defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Probe the string dictionary in the |elements| register. Jump to the 1028defd9ff6930b4e24729971a61cf7469daf119beSteve Block// |done| label if a property with the given name is found leaving the 1038defd9ff6930b4e24729971a61cf7469daf119beSteve Block// index into the dictionary in |r0|. Jump to the |miss| label 1048defd9ff6930b4e24729971a61cf7469daf119beSteve Block// otherwise. 1058defd9ff6930b4e24729971a61cf7469daf119beSteve Blockstatic void GenerateStringDictionaryProbes(MacroAssembler* masm, 1068defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label* miss, 1078defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label* done, 1088defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register elements, 1098defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register name, 1108defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register r0, 1118defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register r1) { 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the capacity mask. 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kCapacityOffset = 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StringDictionary::kHeaderSize + 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StringDictionary::kCapacityIndex * kPointerSize; 1168defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(r1, FieldOperand(elements, kCapacityOffset)); 1178defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ shr(r1, kSmiTagSize); // convert smi to int 1188defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ dec(r1); 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Generate an unrolled loop that performs a few probes before 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // giving up. Measurements done on Gmail indicate that 2 probes 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // cover ~93% of loads from dictionaries. 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kProbes = 4; 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kElementsStartOffset = 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StringDictionary::kHeaderSize + 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StringDictionary::kElementsStartIndex * kPointerSize; 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < kProbes; i++) { 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the masked index: (hash + i + i * i) & mask. 1298defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(r0, FieldOperand(name, String::kHashFieldOffset)); 1308defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ shr(r0, String::kHashShift); 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (i > 0) { 1328defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ add(Operand(r0), Immediate(StringDictionary::GetProbeOffset(i))); 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1348defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ and_(r0, Operand(r1)); 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Scale the index by multiplying by the entry size. 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(StringDictionary::kEntrySize == 3); 1388defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ lea(r0, Operand(r0, r0, times_2, 0)); // r0 = r0 * 3 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the key is identical to the name. 1418defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ cmp(name, Operand(elements, r0, times_4, 1428defd9ff6930b4e24729971a61cf7469daf119beSteve Block kElementsStartOffset - kHeapObjectTag)); 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (i != kProbes - 1) { 1448defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(equal, done, taken); 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1468defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(not_equal, miss, not_taken); 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1498defd9ff6930b4e24729971a61cf7469daf119beSteve Block} 1508defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1518defd9ff6930b4e24729971a61cf7469daf119beSteve Block 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1538defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Helper function used to load a property from a dictionary backing 1548defd9ff6930b4e24729971a61cf7469daf119beSteve Block// storage. This function may fail to load a property even though it is 1558defd9ff6930b4e24729971a61cf7469daf119beSteve Block// in the dictionary, so code at miss_label must always call a backup 1568defd9ff6930b4e24729971a61cf7469daf119beSteve Block// property load that is complete. This function is safe to call if 1578defd9ff6930b4e24729971a61cf7469daf119beSteve Block// name is not a symbol, and will jump to the miss_label in that 1588defd9ff6930b4e24729971a61cf7469daf119beSteve Block// case. The generated code assumes that the receiver has slow 1598defd9ff6930b4e24729971a61cf7469daf119beSteve Block// properties, is not a global object and does not have interceptors. 1608defd9ff6930b4e24729971a61cf7469daf119beSteve Blockstatic void GenerateDictionaryLoad(MacroAssembler* masm, 1618defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label* miss_label, 1628defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register elements, 1638defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register name, 1648defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register r0, 1658defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register r1, 1668defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register result) { 1678defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Register use: 1688defd9ff6930b4e24729971a61cf7469daf119beSteve Block // 1698defd9ff6930b4e24729971a61cf7469daf119beSteve Block // elements - holds the property dictionary on entry and is unchanged. 1708defd9ff6930b4e24729971a61cf7469daf119beSteve Block // 1718defd9ff6930b4e24729971a61cf7469daf119beSteve Block // name - holds the name of the property on entry and is unchanged. 1728defd9ff6930b4e24729971a61cf7469daf119beSteve Block // 1738defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Scratch registers: 1748defd9ff6930b4e24729971a61cf7469daf119beSteve Block // 1758defd9ff6930b4e24729971a61cf7469daf119beSteve Block // r0 - used for the index into the property dictionary 1768defd9ff6930b4e24729971a61cf7469daf119beSteve Block // 1778defd9ff6930b4e24729971a61cf7469daf119beSteve Block // r1 - used to hold the capacity of the property dictionary. 1788defd9ff6930b4e24729971a61cf7469daf119beSteve Block // 1798defd9ff6930b4e24729971a61cf7469daf119beSteve Block // result - holds the result on exit. 1808defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1818defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label done; 1828defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1838defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Probe the dictionary. 1848defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateStringDictionaryProbes(masm, 1858defd9ff6930b4e24729971a61cf7469daf119beSteve Block miss_label, 1868defd9ff6930b4e24729971a61cf7469daf119beSteve Block &done, 1878defd9ff6930b4e24729971a61cf7469daf119beSteve Block elements, 1888defd9ff6930b4e24729971a61cf7469daf119beSteve Block name, 1898defd9ff6930b4e24729971a61cf7469daf119beSteve Block r0, 1908defd9ff6930b4e24729971a61cf7469daf119beSteve Block r1); 1918defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1928defd9ff6930b4e24729971a61cf7469daf119beSteve Block // If probing finds an entry in the dictionary, r0 contains the 1938defd9ff6930b4e24729971a61cf7469daf119beSteve Block // index into the dictionary. Check that the value is a normal 1948defd9ff6930b4e24729971a61cf7469daf119beSteve Block // property. 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&done); 1968defd9ff6930b4e24729971a61cf7469daf119beSteve Block const int kElementsStartOffset = 1978defd9ff6930b4e24729971a61cf7469daf119beSteve Block StringDictionary::kHeaderSize + 1988defd9ff6930b4e24729971a61cf7469daf119beSteve Block StringDictionary::kElementsStartIndex * kPointerSize; 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 2008defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag), 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, miss_label, not_taken); 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the value at the masked, scaled index. 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kValueOffset = kElementsStartOffset + kPointerSize; 2068defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(result, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag)); 2078defd9ff6930b4e24729971a61cf7469daf119beSteve Block} 2088defd9ff6930b4e24729971a61cf7469daf119beSteve Block 2098defd9ff6930b4e24729971a61cf7469daf119beSteve Block 2108defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Helper function used to store a property to a dictionary backing 2118defd9ff6930b4e24729971a61cf7469daf119beSteve Block// storage. This function may fail to store a property eventhough it 2128defd9ff6930b4e24729971a61cf7469daf119beSteve Block// is in the dictionary, so code at miss_label must always call a 2138defd9ff6930b4e24729971a61cf7469daf119beSteve Block// backup property store that is complete. This function is safe to 2148defd9ff6930b4e24729971a61cf7469daf119beSteve Block// call if name is not a symbol, and will jump to the miss_label in 2158defd9ff6930b4e24729971a61cf7469daf119beSteve Block// that case. The generated code assumes that the receiver has slow 2168defd9ff6930b4e24729971a61cf7469daf119beSteve Block// properties, is not a global object and does not have interceptors. 2178defd9ff6930b4e24729971a61cf7469daf119beSteve Blockstatic void GenerateDictionaryStore(MacroAssembler* masm, 2188defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label* miss_label, 2198defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register elements, 2208defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register name, 2218defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register value, 2228defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register r0, 2238defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register r1) { 2248defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Register use: 2258defd9ff6930b4e24729971a61cf7469daf119beSteve Block // 2268defd9ff6930b4e24729971a61cf7469daf119beSteve Block // elements - holds the property dictionary on entry and is clobbered. 2278defd9ff6930b4e24729971a61cf7469daf119beSteve Block // 2288defd9ff6930b4e24729971a61cf7469daf119beSteve Block // name - holds the name of the property on entry and is unchanged. 2298defd9ff6930b4e24729971a61cf7469daf119beSteve Block // 2308defd9ff6930b4e24729971a61cf7469daf119beSteve Block // value - holds the value to store and is unchanged. 2318defd9ff6930b4e24729971a61cf7469daf119beSteve Block // 2328defd9ff6930b4e24729971a61cf7469daf119beSteve Block // r0 - used for index into the property dictionary and is clobbered. 2338defd9ff6930b4e24729971a61cf7469daf119beSteve Block // 2348defd9ff6930b4e24729971a61cf7469daf119beSteve Block // r1 - used to hold the capacity of the property dictionary and is clobbered. 2358defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label done; 2368defd9ff6930b4e24729971a61cf7469daf119beSteve Block 2378defd9ff6930b4e24729971a61cf7469daf119beSteve Block 2388defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Probe the dictionary. 2398defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateStringDictionaryProbes(masm, 2408defd9ff6930b4e24729971a61cf7469daf119beSteve Block miss_label, 2418defd9ff6930b4e24729971a61cf7469daf119beSteve Block &done, 2428defd9ff6930b4e24729971a61cf7469daf119beSteve Block elements, 2438defd9ff6930b4e24729971a61cf7469daf119beSteve Block name, 2448defd9ff6930b4e24729971a61cf7469daf119beSteve Block r0, 2458defd9ff6930b4e24729971a61cf7469daf119beSteve Block r1); 2468defd9ff6930b4e24729971a61cf7469daf119beSteve Block 2478defd9ff6930b4e24729971a61cf7469daf119beSteve Block // If probing finds an entry in the dictionary, r0 contains the 2488defd9ff6930b4e24729971a61cf7469daf119beSteve Block // index into the dictionary. Check that the value is a normal 2498defd9ff6930b4e24729971a61cf7469daf119beSteve Block // property that is not read only. 2508defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ bind(&done); 2518defd9ff6930b4e24729971a61cf7469daf119beSteve Block const int kElementsStartOffset = 2528defd9ff6930b4e24729971a61cf7469daf119beSteve Block StringDictionary::kHeaderSize + 2538defd9ff6930b4e24729971a61cf7469daf119beSteve Block StringDictionary::kElementsStartIndex * kPointerSize; 2548defd9ff6930b4e24729971a61cf7469daf119beSteve Block const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 2558defd9ff6930b4e24729971a61cf7469daf119beSteve Block const int kTypeAndReadOnlyMask 2568defd9ff6930b4e24729971a61cf7469daf119beSteve Block = (PropertyDetails::TypeField::mask() | 2578defd9ff6930b4e24729971a61cf7469daf119beSteve Block PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize; 2588defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag), 2598defd9ff6930b4e24729971a61cf7469daf119beSteve Block Immediate(kTypeAndReadOnlyMask)); 2608defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(not_zero, miss_label, not_taken); 2618defd9ff6930b4e24729971a61cf7469daf119beSteve Block 2628defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Store the value at the masked, scaled index. 2638defd9ff6930b4e24729971a61cf7469daf119beSteve Block const int kValueOffset = kElementsStartOffset + kPointerSize; 2648defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ lea(r0, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag)); 2658defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(Operand(r0, 0), value); 2668defd9ff6930b4e24729971a61cf7469daf119beSteve Block 2678defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Update write barrier. Make sure not to clobber the value. 2688defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(r1, value); 2698defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ RecordWrite(elements, r0, r1); 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2736ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void GenerateNumberDictionaryLoad(MacroAssembler* masm, 2746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* miss, 2756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register elements, 2766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register key, 2776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register r0, 2786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register r1, 2797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register r2, 2807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result) { 2816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Register use: 2826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 2836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // elements - holds the slow-case elements of the receiver and is unchanged. 2846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 2857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // key - holds the smi key on entry and is unchanged. 2866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 2876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Scratch registers: 2886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 2896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // r0 - holds the untagged key on entry and holds the hash once computed. 2906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 2916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // r1 - used to hold the capacity mask of the dictionary 2926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 2936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // r2 - used for the index into the dictionary. 2947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // 2957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // result - holds the result on exit if the load succeeds and we fall through. 2967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label done; 2986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Compute the hash code from the untagged key. This must be kept in sync 3006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // with ComputeIntegerHash in utils.h. 3016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 3026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // hash = ~hash + (hash << 15); 3036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r1, r0); 3046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ not_(r0); 3056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ shl(r1, 15); 3066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ add(r0, Operand(r1)); 3076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // hash = hash ^ (hash >> 12); 3086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r1, r0); 3096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ shr(r1, 12); 3106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ xor_(r0, Operand(r1)); 3116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // hash = hash + (hash << 2); 3126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ lea(r0, Operand(r0, r0, times_4, 0)); 3136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // hash = hash ^ (hash >> 4); 3146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r1, r0); 3156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ shr(r1, 4); 3166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ xor_(r0, Operand(r1)); 3176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // hash = hash * 2057; 3186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ imul(r0, r0, 2057); 3196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // hash = hash ^ (hash >> 16); 3206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r1, r0); 3216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ shr(r1, 16); 3226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ xor_(r0, Operand(r1)); 3236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Compute capacity mask. 3256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r1, FieldOperand(elements, NumberDictionary::kCapacityOffset)); 3266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ shr(r1, kSmiTagSize); // convert smi to int 3276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ dec(r1); 3286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Generate an unrolled loop that performs a few probes before giving up. 3306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kProbes = 4; 3316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (int i = 0; i < kProbes; i++) { 3326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Use r2 for index calculations and keep the hash intact in r0. 3336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r2, r0); 3346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Compute the masked index: (hash + i + i * i) & mask. 3356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (i > 0) { 3366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ add(Operand(r2), Immediate(NumberDictionary::GetProbeOffset(i))); 3376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ and_(r2, Operand(r1)); 3396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Scale the index by multiplying by the entry size. 3416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(NumberDictionary::kEntrySize == 3); 3426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 3436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check if the key matches. 3456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(key, FieldOperand(elements, 3466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block r2, 3476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block times_pointer_size, 3486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NumberDictionary::kElementsStartOffset)); 3496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (i != (kProbes - 1)) { 3506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(equal, &done, taken); 3516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 3526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_equal, miss, not_taken); 3536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&done); 3576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the value is a normal propety. 3586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kDetailsOffset = 3596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NumberDictionary::kElementsStartOffset + 2 * kPointerSize; 3606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT_EQ(NORMAL, 0); 3616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), 3626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); 3636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_zero, miss); 3646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the value at the masked, scaled index. 3666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kValueOffset = 3676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NumberDictionary::kElementsStartOffset + kPointerSize; 3687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); 3696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 3706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The offset from the inlined patch site to the start of the 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// inlined load instruction. It is 7 bytes (test eax, imm) plus 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6 bytes (jne slow_label). 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int LoadIC::kOffsetToLoadInstruction = 13; 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateArrayLength(MacroAssembler* masm) { 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 380402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadArrayLength(masm, eax, edx, &miss); 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateStringLength(MacroAssembler* masm) { 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 394402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 400402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu StubCompiler::GenerateLoadStringLength(masm, eax, edx, ebx, &miss); 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) { 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 408402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadFunctionPrototype(masm, eax, edx, ebx, &miss); 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Checks the receiver for special cases (value type, slow case bits). 4217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Falls through for regular JS object. 4227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, 4237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register receiver, 4249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Register map, 4258defd9ff6930b4e24729971a61cf7469daf119beSteve Block int interceptor_bit, 4267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label* slow) { 4277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Register use: 4287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // receiver - holds the receiver and is unchanged. 4297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Scratch registers: 4309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // map - used to hold the map of the receiver. 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object isn't a smi. 4337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test(receiver, Immediate(kSmiTagMask)); 4347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(zero, slow, not_taken); 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the map of the receiver. 4379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ mov(map, FieldOperand(receiver, HeapObject::kMapOffset)); 438d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 439d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Check bit field. 4409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ test_b(FieldOperand(map, Map::kBitFieldOffset), 4418defd9ff6930b4e24729971a61cf7469daf119beSteve Block (1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit)); 4427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(not_zero, slow, not_taken); 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is some kind of JS object EXCEPT JS Value type. 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // In the case that the object is a value-wrapper object, 445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // we enter the runtime system to make sure that indexing 4467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // into string objects works as intended. 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); 4487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 4499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ CmpInstanceType(map, JS_OBJECT_TYPE); 4507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(below, slow, not_taken); 4517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 4527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 4537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 4547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Loads an indexed element from a fast case array. 4557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void GenerateFastArrayLoad(MacroAssembler* masm, 4567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register receiver, 4577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register key, 4587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch, 4597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result, 4607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label* not_fast_array, 4617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label* out_of_range) { 4627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Register use: 4637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // receiver - holds the receiver and is unchanged. 4647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // key - holds the key and is unchanged (must be a smi). 4657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Scratch registers: 4667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // scratch - used to hold elements of the receiver and the loaded value. 4677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // result - holds the result on exit if the load succeeds and 4687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // we fall through. 4697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 4707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(scratch, FieldOperand(receiver, JSObject::kElementsOffset)); 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is in fast mode (not dictionary). 4727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ CheckMap(scratch, Factory::fixed_array_map(), not_fast_array, true); 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the key (index) is within bounds. 4747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ cmp(key, FieldOperand(scratch, FixedArray::kLengthOffset)); 4757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(above_equal, out_of_range); 476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fast case: Do the load. 4777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0)); 4787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(scratch, FieldOperand(scratch, key, times_2, FixedArray::kHeaderSize)); 4797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ cmp(Operand(scratch), Immediate(Factory::the_hole_value())); 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // In case the loaded value is the_hole we have to consult GetProperty 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to ensure the prototype chain is searched. 4827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(equal, out_of_range); 4837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (!result.is(scratch)) { 4847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(result, scratch); 4857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 4867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 4877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 4887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 4897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Checks whether a key is an array index string or a symbol string. 4909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen// Falls through if the key is a symbol. 4917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void GenerateKeyStringCheck(MacroAssembler* masm, 4927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register key, 4937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register map, 4947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register hash, 4957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label* index_string, 4967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label* not_symbol) { 4977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Register use: 4987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // key - holds the key and is unchanged. Assumed to be non-smi. 4997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Scratch registers: 5007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // map - used to hold the map of the key. 5017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // hash - used to hold the hash of the key. 5027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ CmpObjectType(key, FIRST_NONSTRING_TYPE, map); 5037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(above_equal, not_symbol); 5047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 5057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Is the string an array index, with cached numeric value? 5067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(hash, FieldOperand(key, String::kHashFieldOffset)); 5077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test(hash, Immediate(String::kContainsCachedArrayIndexMask)); 5087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(zero, index_string, not_taken); 5097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 5107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Is the string a symbol? 5117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(kSymbolTag != 0); 5127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsSymbolMask); 5137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(zero, not_symbol, not_taken); 5147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 5157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 5167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 5177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Picks out an array index from the hash field. 5187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void GenerateIndexFromHash(MacroAssembler* masm, 5197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register key, 5209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Register hash) { 5217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Register use: 5227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // key - holds the overwritten key on exit. 5237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // hash - holds the key's hash. Clobbered. 5247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 5257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // The assert checks that the constants for the maximum number of digits 5267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // for an array index cached in the hash field and the number of bits 5277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // reserved for it does not conflict. 5287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < 5297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch (1 << String::kArrayIndexValueBits)); 5307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // We want the smi-tagged index in key. kArrayIndexValueMask has zeros in 5317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // the low kHashShift bits. 5327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(String::kHashShift >= kSmiTagSize); 5337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ and_(hash, String::kArrayIndexValueMask); 5347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ shr(hash, String::kHashShift - kSmiTagSize); 5357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Here we actually clobber the key which will be used if calling into 5367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // runtime later. However as the new key is the numeric value of a string key 5377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // there is no difference in using either key. 5387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(key, hash); 5397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 5407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 5417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 5427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 5437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------- S t a t e ------------- 5447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- eax : key 5457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- edx : receiver 5467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[0] : return address 5477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------------------------------- 548bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Label slow, check_string, index_smi, index_string, property_array_property; 5497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label check_pixel_array, probe_dictionary, check_number_dictionary; 5507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 5517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the key is a smi. 5527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test(eax, Immediate(kSmiTagMask)); 5537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(not_zero, &check_string, not_taken); 5547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_smi); 5557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Now the key is known to be a smi. This place is also jumped to from 5567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // where a numeric string is converted to a smi. 5577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 5588defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateKeyedLoadReceiverCheck( 5598defd9ff6930b4e24729971a61cf7469daf119beSteve Block masm, edx, ecx, Map::kHasIndexedInterceptor, &slow); 5608defd9ff6930b4e24729971a61cf7469daf119beSteve Block 5617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateFastArrayLoad(masm, 5627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch edx, 5637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch eax, 5647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ecx, 5657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch eax, 5667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &check_pixel_array, 5677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &slow); 568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); 569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&check_pixel_array); 572402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Check whether the elements is a pixel array. 573402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // edx: receiver 574402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // eax: key 575402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ecx: elements 5767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(ebx, eax); 5777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ SmiUntag(ebx); 5786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CheckMap(ecx, Factory::pixel_array_map(), &check_number_dictionary, true); 579402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(ebx, FieldOperand(ecx, PixelArray::kLengthOffset)); 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &slow); 581402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, FieldOperand(ecx, PixelArray::kExternalPointerOffset)); 582402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(eax, Operand(eax, ebx, times_1, 0)); 583402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ SmiTag(eax); 584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&check_number_dictionary); 5876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check whether the elements is a number dictionary. 5886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver 5896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ebx: untagged index 5906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // eax: key 5916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: elements 5926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CheckMap(ecx, Factory::hash_table_map(), &slow, true); 5936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label slow_pop_receiver; 5946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Push receiver on the stack to free up a register for the dictionary 5956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // probing. 5966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(edx); 5976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GenerateNumberDictionaryLoad(masm, 5986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block &slow_pop_receiver, 5996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ecx, 6006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block eax, 6016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ebx, 6026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block edx, 6037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch edi, 6047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch eax); 6056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Pop receiver before returning. 6066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(edx); 6076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret(0); 6086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&slow_pop_receiver); 6106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Pop the receiver from the stack and jump to runtime. 6116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(edx); 6126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&slow); 614402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Slow case: jump to runtime. 615402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // edx: receiver 616402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // eax: key 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); 618402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateRuntimeGetProperty(masm); 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&check_string); 6217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateKeyStringCheck(masm, eax, ecx, ebx, &index_string, &slow); 622e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 6238defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateKeyedLoadReceiverCheck( 6248defd9ff6930b4e24729971a61cf7469daf119beSteve Block masm, edx, ecx, Map::kHasNamedInterceptor, &slow); 6258defd9ff6930b4e24729971a61cf7469daf119beSteve Block 626e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // If the receiver is a fast-case object, check the keyed lookup 627402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // cache. Otherwise probe the dictionary. 628402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset)); 629e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 630e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Immediate(Factory::hash_table_map())); 631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, &probe_dictionary); 632e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 633e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Load the map of the receiver, compute the keyed lookup cache hash 634e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // based on 32 bits of the map pointer and the string hash. 635402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); 636402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, ebx); 637402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ shr(ecx, KeyedLookupCache::kMapHashShift); 638402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(edi, FieldOperand(eax, String::kHashFieldOffset)); 639402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ shr(edi, String::kHashShift); 640402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ xor_(ecx, Operand(edi)); 641402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ and_(ecx, KeyedLookupCache::kCapacityMask); 642e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 643e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Load the key (consisting of map and symbol) from the cache and 644e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // check for match. 645e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ExternalReference cache_keys 646e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke = ExternalReference::keyed_lookup_cache_keys(); 647402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(edi, ecx); 648e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ shl(edi, kPointerSizeLog2 + 1); 649e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys)); 650e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_equal, &slow); 651e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ add(Operand(edi), Immediate(kPointerSize)); 652402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(eax, Operand::StaticArray(edi, times_1, cache_keys)); 653e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_equal, &slow); 654e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 655bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Get field offset. 656402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // edx : receiver 657402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ebx : receiver's map 658402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // eax : key 659402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ecx : lookup cache index 660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ExternalReference cache_field_offsets 661e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke = ExternalReference::keyed_lookup_cache_field_offsets(); 662402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(edi, 663402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Operand::StaticArray(ecx, times_pointer_size, cache_field_offsets)); 664402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(ecx, FieldOperand(ebx, Map::kInObjectPropertiesOffset)); 6657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ sub(edi, Operand(ecx)); 666bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ j(above_equal, &property_array_property); 667e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 668e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Load in-object property. 669402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset)); 670402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ add(ecx, Operand(edi)); 671402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, FieldOperand(edx, ecx, times_pointer_size, 0)); 6727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ IncrementCounter(&Counters::keyed_load_generic_lookup_cache, 1); 673e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ret(0); 674e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 675bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Load property array property. 676bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&property_array_property); 677bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ mov(eax, FieldOperand(edx, JSObject::kPropertiesOffset)); 678bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ mov(eax, FieldOperand(eax, edi, times_pointer_size, 679bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch FixedArray::kHeaderSize)); 680bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ IncrementCounter(&Counters::keyed_load_generic_lookup_cache, 1); 681bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ ret(0); 682bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 683e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Do a quick inline probe of the receiver's dictionary, if it 684e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // exists. 685e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&probe_dictionary); 6868defd9ff6930b4e24729971a61cf7469daf119beSteve Block 6878defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(ecx, FieldOperand(edx, JSObject::kMapOffset)); 6888defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 6898defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateGlobalInstanceTypeCheck(masm, ecx, &slow); 6908defd9ff6930b4e24729971a61cf7469daf119beSteve Block 6918defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateDictionaryLoad(masm, &slow, ebx, eax, ecx, edi, eax); 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); 693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 694e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&index_string); 6969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateIndexFromHash(masm, eax, ebx); 6979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Now jump to the place where smi keys are handled. 6989dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ jmp(&index_smi); 699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 702e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid KeyedLoadIC::GenerateString(MacroAssembler* masm) { 703e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------- S t a t e ------------- 7046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- eax : key (index) 705402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 706e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 707e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------------------------------- 7086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss; 7096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label index_out_of_range; 7106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 7116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register receiver = edx; 7126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register index = eax; 7137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch1 = ebx; 7147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch2 = ecx; 7157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = eax; 7167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 7177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharAtGenerator char_at_generator(receiver, 7187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch index, 7197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch1, 7207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch2, 7217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch result, 7227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &miss, // When not a string. 7237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &miss, // When not a number. 7247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &index_out_of_range, 7257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch STRING_INDEX_IS_ARRAY_INDEX); 7267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch char_at_generator.GenerateFast(masm); 7277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ ret(0); 7287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 7297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ICRuntimeCallHelper call_helper; 7307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch char_at_generator.GenerateSlow(masm, call_helper); 731e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 7326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&index_out_of_range); 7336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Set(eax, Immediate(Factory::undefined_value())); 7346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret(0); 735e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 736e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&miss); 737e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke GenerateMiss(masm); 738e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 739e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 740e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 7413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm, 7423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ExternalArrayType array_type) { 7433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ----------- S t a t e ------------- 744402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 745402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 7463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // -- esp[0] : return address 7473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ----------------------------------- 7483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label slow, failed_allocation; 7493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the object isn't a smi. 751402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ test(edx, Immediate(kSmiTagMask)); 7523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(zero, &slow, not_taken); 7533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the key is a smi. 7553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ test(eax, Immediate(kSmiTagMask)); 7563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_zero, &slow, not_taken); 7573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Get the map of the receiver. 759402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 7603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the receiver does not require access checks. We need 7613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // to check this explicitly since this generic stub does not perform 7623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // map checks. 7637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 7647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1 << Map::kIsAccessCheckNeeded); 7653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_zero, &slow, not_taken); 7663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 767402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CmpInstanceType(ecx, JS_OBJECT_TYPE); 7683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, &slow, not_taken); 7693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the elements array is the appropriate type of 7713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ExternalArray. 772402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); 7733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Handle<Map> map(Heap::MapForExternalArrayType(array_type)); 774402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 7753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Immediate(map)); 7763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, &slow, not_taken); 7773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 778402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // eax: key, known to be a smi. 779402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // edx: receiver, known to be a JSObject. 780402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ebx: elements object, known to be an external array. 7813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the index is in range. 782402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, eax); 783402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ SmiUntag(ecx); // Untag the index. 784402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset)); 7853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Unsigned comparison catches both negative and too-large values. 7863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(above_equal, &slow); 7873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 788402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset)); 789402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ebx: base pointer of external storage 7903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block switch (array_type) { 7913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalByteArray: 792402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movsx_b(ecx, Operand(ebx, ecx, times_1, 0)); 7933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 7943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedByteArray: 795402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(ecx, Operand(ebx, ecx, times_1, 0)); 7963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 7973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalShortArray: 798402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movsx_w(ecx, Operand(ebx, ecx, times_2, 0)); 7993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 8003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedShortArray: 801402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_w(ecx, Operand(ebx, ecx, times_2, 0)); 8023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 8033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalIntArray: 8043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedIntArray: 805402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, Operand(ebx, ecx, times_4, 0)); 8063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 8073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalFloatArray: 808402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ fld_s(Operand(ebx, ecx, times_4, 0)); 8093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 8103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block default: 8113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block UNREACHABLE(); 8123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 8133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 8143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // For integer array types: 816402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ecx: value 8173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // For floating-point array type: 8183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // FP(0): value 8193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (array_type == kExternalIntArray || 8213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block array_type == kExternalUnsignedIntArray) { 8223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // For the Int and UnsignedInt array types, we need to see whether 8233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // the value can be represented in a Smi. If not, we need to convert 8243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // it to a HeapNumber. 8253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label box_int; 8263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (array_type == kExternalIntArray) { 827402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(ecx, 0xC0000000); 828402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ j(sign, &box_int); 8293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 8303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT_EQ(array_type, kExternalUnsignedIntArray); 8313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // The test is different for unsigned int values. Since we need 832402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // the value to be in the range of a positive smi, we can't 8333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // handle either of the top two bits being set in the value. 834402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ test(ecx, Immediate(0xC0000000)); 8353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_zero, &box_int); 8363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 8373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 838402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, ecx); 839402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ SmiTag(eax); 8403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ret(0); 8413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&box_int); 8433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Allocate a HeapNumber for the int and perform int-to-double 8453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // conversion. 8463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (array_type == kExternalIntArray) { 847402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(ecx); 8483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fild_s(Operand(esp, 0)); 849402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(ecx); 8503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 8513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(array_type == kExternalUnsignedIntArray); 8523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Need to zero-extend the value. 8533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // There's no fild variant for unsigned values, so zero-extend 8543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // to a 64-bit int manually. 8553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(Immediate(0)); 856402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(ecx); 8573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fild_d(Operand(esp, 0)); 858402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(ecx); 859402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(ecx); 8603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 8613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // FP(0): value 862402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); 8633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Set the value. 864402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, ecx); 8653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 8663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ret(0); 8673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (array_type == kExternalFloatArray) { 8683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // For the floating-point array type, we need to always allocate a 8693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // HeapNumber. 870402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); 8713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Set the value. 872402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, ecx); 8733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 8743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ret(0); 8753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 876402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, ecx); 877402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ SmiTag(eax); 8783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ret(0); 8793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 8803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If we fail allocation of the HeapNumber, we still have a value on 8823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // top of the FPU stack. Remove it. 8833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&failed_allocation); 8843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ffree(); 8853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fincstp(); 8863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Fall through to slow case. 8873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Slow case: Jump to runtime. 8893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&slow); 8903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1); 891402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateRuntimeGetProperty(masm); 892402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 893402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 894402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 895402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { 896402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------- S t a t e ------------- 897402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 898402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 899402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- esp[0] : return address 900402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------------------------------- 901402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label slow; 902402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 903402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Check that the receiver isn't a smi. 904402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ test(edx, Immediate(kSmiTagMask)); 905402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ j(zero, &slow, not_taken); 906402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 907402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Check that the key is a smi. 908402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ test(eax, Immediate(kSmiTagMask)); 909402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ j(not_zero, &slow, not_taken); 910402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 911402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Get the map of the receiver. 912402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 913402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 914402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Check that it has indexed interceptor and access checks 915402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // are not enabled for this object. 916402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(ecx, FieldOperand(ecx, Map::kBitFieldOffset)); 917402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ and_(Operand(ecx), Immediate(kSlowCaseBitFieldMask)); 918402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(Operand(ecx), Immediate(1 << Map::kHasIndexedInterceptor)); 919402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ j(not_zero, &slow, not_taken); 920402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 921402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Everything is fine, call runtime. 922402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(ecx); 923402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(edx); // receiver 924402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(eax); // key 925402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(ecx); // return address 926402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 927402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Perform tail call to the entry. 9286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference ref = ExternalReference( 9296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block IC_Utility(kKeyedLoadPropertyWithInterceptor)); 9306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(ref, 2, 1); 931402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 932402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ bind(&slow); 933402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateMiss(masm); 9343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 9353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { 938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 9406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : key 9416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- edx : receiver 942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label slow, fast, array, extra, check_pixel_array; 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object isn't a smi. 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(edx, Immediate(kSmiTagMask)); 948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &slow, not_taken); 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the map from the receiver. 9506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver does not require access checks. We need 952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to do this because this generic stub does not perform map checks. 9537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test_b(FieldOperand(edi, Map::kBitFieldOffset), 9547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1 << Map::kIsAccessCheckNeeded); 955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &slow, not_taken); 956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the key is a smi. 9576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(ecx, Immediate(kSmiTagMask)); 958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &slow, not_taken); 9596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CmpInstanceType(edi, JS_ARRAY_TYPE); 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &array); 961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is some kind of JS object. 9626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE); 9636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(below, &slow, not_taken); 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Object case: Check key against length in the elements array. 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: value 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edx: JSObject 9686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: key (a smi) 9696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is in fast mode (not dictionary). 9716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true); 9727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); 973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(below, &fast, taken); 974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Slow case: call runtime. 976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&slow); 977402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateRuntimeSetProperty(masm); 978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check whether the elements is a pixel array. 980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&check_pixel_array); 9816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // eax: value 9827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ecx: key (a smi) 9836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver 9846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edi: elements array 9856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CheckMap(edi, Factory::pixel_array_map(), &slow, true); 986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the value is a smi. If a conversion is needed call into the 987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // runtime to convert and clamp. 988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(eax, Immediate(kSmiTagMask)); 989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &slow); 9906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ebx, ecx); 9916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ SmiUntag(ebx); 9926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(ebx, FieldOperand(edi, PixelArray::kLengthOffset)); 993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &slow); 9946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ecx, eax); // Save the value. Key is not longer needed. 9956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ SmiUntag(ecx); 996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { // Clamp the value to [0..255]. 9973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label done; 9986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(ecx, Immediate(0xFFFFFF00)); 999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &done); 10006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ setcc(negative, ecx); // 1 if negative, 0 if positive. 10016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ dec_b(ecx); // 0 if negative, 255 if positive. 1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&done); 1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 10046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edi, FieldOperand(edi, PixelArray::kExternalPointerOffset)); 10056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov_b(Operand(edi, ebx, times_1, 0), ecx); 10066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret(0); // Return value in eax. 1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Extra capacity case: Check if there is extra capacity to 1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // perform the store and update the length. Used for adding one 1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // element to the array by writing to array[array.length]. 1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&extra); 1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: value 10136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver, a JSArray 10146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: key, a smi. 10156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edi: receiver->elements, a FixedArray 10166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // flags: compare (ecx, edx.length()) 1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &slow, not_taken); // do not leave holes in the array 10187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); 1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &slow, not_taken); 10206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Add 1 to receiver->length, and go to fast array write. 10216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ add(FieldOperand(edx, JSArray::kLengthOffset), 10227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Immediate(Smi::FromInt(1))); 1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&fast); 1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Array case: Get the length and the elements array from the JS 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // array. Check that the array is in fast mode; if it is the 1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // length is always a smi. 1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&array); 1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: value 10306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver, a JSArray 10316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: key, a smi. 10326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 10336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true); 1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the key against the length in the array, compute the 1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // address to store into and fall through to fast case. 10376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. 1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &extra, not_taken); 1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fast case: Do the store. 1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fast); 1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: value 10436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: key (a smi) 10446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver 10456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edi: FixedArray receiver->elements 104625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ mov(CodeGenerator::FixedArrayElementOperand(edi, ecx), eax); 1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update write barrier for the elements array address. 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(eax)); 10496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ RecordWrite(edi, 0, edx, ecx); 1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm, 10553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ExternalArrayType array_type) { 10563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ----------- S t a t e ------------- 10573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // -- eax : value 10586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : key 10596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- edx : receiver 10603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // -- esp[0] : return address 10613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ----------------------------------- 10623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label slow, check_heap_number; 10633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the object isn't a smi. 10653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ test(edx, Immediate(kSmiTagMask)); 10663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(zero, &slow); 10673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Get the map from the receiver. 10686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); 10693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the receiver does not require access checks. We need 10703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // to do this because this generic stub does not perform map checks. 10717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test_b(FieldOperand(edi, Map::kBitFieldOffset), 10727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1 << Map::kIsAccessCheckNeeded); 10733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_zero, &slow); 10743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the key is a smi. 10756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(ecx, Immediate(kSmiTagMask)); 10763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_zero, &slow); 10773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Get the instance type from the map of the receiver. 10786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CmpInstanceType(edi, JS_OBJECT_TYPE); 10793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, &slow); 10803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the elements array is the appropriate type of 10823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ExternalArray. 10833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // eax: value 10846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver, a JSObject 10856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: key, a smi 10866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 10876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CheckMap(edi, Handle<Map>(Heap::MapForExternalArrayType(array_type)), 10886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block &slow, true); 10893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the index is in range. 10916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ebx, ecx); 10926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ SmiUntag(ebx); 10936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(ebx, FieldOperand(edi, ExternalArray::kLengthOffset)); 10943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Unsigned comparison catches both negative and too-large values. 10953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(above_equal, &slow); 10963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Handle both smis and HeapNumbers in the fast path. Go to the 10983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // runtime for all other kinds of values. 10993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // eax: value 11006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver 11016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: key 11026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edi: elements array 11033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ebx: untagged index 11043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ test(eax, Immediate(kSmiTagMask)); 11053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, &check_heap_number); 11063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // smi case 11076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ecx, eax); // Preserve the value in eax. Key is no longer needed. 11086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ SmiUntag(ecx); 11096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); 11103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ecx: base pointer of external storage 11113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block switch (array_type) { 11123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalByteArray: 11133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedByteArray: 11146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov_b(Operand(edi, ebx, times_1, 0), ecx); 11153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 11163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalShortArray: 11173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedShortArray: 11186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov_w(Operand(edi, ebx, times_2, 0), ecx); 11193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 11203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalIntArray: 11213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedIntArray: 11226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(Operand(edi, ebx, times_4, 0), ecx); 11233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 11243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalFloatArray: 11253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Need to perform int-to-float conversion. 11266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(ecx); 11273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fild_s(Operand(esp, 0)); 11286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(ecx); 11296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ fstp_s(Operand(edi, ebx, times_4, 0)); 11303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 11313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block default: 11323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block UNREACHABLE(); 11333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 11343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 11356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret(0); // Return the original value. 11363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 11373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&check_heap_number); 11386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // eax: value 11396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver 11406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: key 11416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edi: elements array 11426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ebx: untagged index 11433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 11443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Immediate(Factory::heap_number_map())); 11453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, &slow); 11463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 11473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // The WebGL specification leaves the behavior of storing NaN and 11483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // +/-Infinity into integer arrays basically undefined. For more 11493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // reproducible behavior, convert these to zero. 11503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); 11516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); 11523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ebx: untagged index 11536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edi: base pointer of external storage 11543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // top of FPU stack: value 11553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (array_type == kExternalFloatArray) { 11566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ fstp_s(Operand(edi, ebx, times_4, 0)); 11573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ret(0); 11583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 11593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Need to perform float-to-int conversion. 11603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Test the top of the FP stack for NaN. 11613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label is_nan; 11623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fucomi(0); 11633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(parity_even, &is_nan); 11643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 11653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (array_type != kExternalUnsignedIntArray) { 11666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(ecx); // Make room on stack 11673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fistp_s(Operand(esp, 0)); 11686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(ecx); 11693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 11703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // fistp stores values as signed integers. 11713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // To represent the entire range, we need to store as a 64-bit 11723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // int and discard the high 32 bits. 11736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ sub(Operand(esp), Immediate(2 * kPointerSize)); 11743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fistp_d(Operand(esp, 0)); 11756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(ecx); 11766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ add(Operand(esp), Immediate(kPointerSize)); 11773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 11786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: untagged integer value 11793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block switch (array_type) { 11803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalByteArray: 11813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedByteArray: 11826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov_b(Operand(edi, ebx, times_1, 0), ecx); 11833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 11843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalShortArray: 11853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedShortArray: 11866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov_w(Operand(edi, ebx, times_2, 0), ecx); 11873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 11883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalIntArray: 11893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedIntArray: { 11903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // We also need to explicitly check for +/-Infinity. These are 11913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // converted to MIN_INT, but we need to be careful not to 11923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // confuse with legal uses of MIN_INT. 11933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label not_infinity; 11943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // This test would apparently detect both NaN and Infinity, 11953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // but we've already checked for NaN using the FPU hardware 11963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // above. 11976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov_w(edx, FieldOperand(eax, HeapNumber::kValueOffset + 6)); 11986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ and_(edx, 0x7FF0); 11996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(edx, 0x7FF0); 12003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, ¬_infinity); 12016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ecx, 0); 12023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(¬_infinity); 12036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(Operand(edi, ebx, times_4, 0), ecx); 12043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 12053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block default: 12073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block UNREACHABLE(); 12083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 12093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret(0); // Return original value. 12113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&is_nan); 12133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ffree(); 12143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fincstp(); 12153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block switch (array_type) { 12163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalByteArray: 12173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedByteArray: 12186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov_b(Operand(edi, ebx, times_1, 0), 0); 12193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 12203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalShortArray: 12213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedShortArray: 12226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ xor_(ecx, Operand(ecx)); 12236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov_w(Operand(edi, ebx, times_2, 0), ecx); 12243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 12253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalIntArray: 12263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedIntArray: 12276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(Operand(edi, ebx, times_4, 0), Immediate(0)); 12283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 12293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block default: 12303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block UNREACHABLE(); 12313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 12323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret(0); // Return the original value. 12343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Slow case: call runtime. 12373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&slow); 1238402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateRuntimeSetProperty(masm); 12393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 12403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Defined in ic.cc. 1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* CallIC_Miss(Arguments args); 1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// The generated code does not accept smi keys. 12467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// The generated code falls through if both probes miss. 12477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void GenerateMonomorphicCacheProbe(MacroAssembler* masm, 12487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int argc, 12499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Code::Kind kind) { 1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1251e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 12527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- edx : receiver 1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 12549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Label number, non_number, non_string, boolean, probe, miss; 1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the stub cache. 1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Flags flags = 12587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Code::ComputeFlags(kind, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc); 1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, eax); 1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the stub cache probing failed, the receiver might be a value. 1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // For value objects, we use the map of the prototype objects for 1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the corresponding JSValue for the cache and that is what we need 1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to probe. 1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for number. 1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(edx, Immediate(kSmiTagMask)); 1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &number, not_taken); 1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ebx); 1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &non_number, taken); 1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&number); 1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadGlobalFunctionPrototype( 1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm, Context::NUMBER_FUNCTION_INDEX, edx); 1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&probe); 1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for string. 1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&non_number); 12787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ CmpInstanceType(ebx, FIRST_NONSTRING_TYPE); 1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &non_string, taken); 1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadGlobalFunctionPrototype( 1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm, Context::STRING_FUNCTION_INDEX, edx); 1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&probe); 1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for boolean. 1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&non_string); 1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(edx, Factory::true_value()); 1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &boolean, not_taken); 1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(edx, Factory::false_value()); 12899dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ j(not_equal, &miss, taken); 1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&boolean); 1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadGlobalFunctionPrototype( 1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm, Context::BOOLEAN_FUNCTION_INDEX, edx); 1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the stub cache for the value object. 1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&probe); 1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg); 12979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ bind(&miss); 1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13018defd9ff6930b4e24729971a61cf7469daf119beSteve Blockstatic void GenerateFunctionTailCall(MacroAssembler* masm, 13028defd9ff6930b4e24729971a61cf7469daf119beSteve Block int argc, 13038defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label* miss) { 1304e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------- S t a t e ------------- 1305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 13068defd9ff6930b4e24729971a61cf7469daf119beSteve Block // -- edi : function 1307e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 1308e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1309e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 1310e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 1311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------------------------------- 1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1313e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the result is not a smi. 1314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ test(edi, Immediate(kSmiTagMask)); 1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, miss, not_taken); 1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1317e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the value is a JavaScript function, fetching its map into eax. 1318e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax); 1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, miss, not_taken); 1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the function. 1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount actual(argc); 1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeFunction(edi, actual, JUMP_FUNCTION); 1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen// The generated code falls through if the call should be handled by runtime. 13279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenstatic void GenerateCallNormal(MacroAssembler* masm, int argc) { 1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1329e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 1330e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 1331e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1332e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 1333e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 13358defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label miss; 1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver of the function from the stack; 1 ~ return address. 1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13408defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateStringDictionaryReceiverCheck(masm, edx, eax, ebx, &miss); 1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13428defd9ff6930b4e24729971a61cf7469daf119beSteve Block // eax: elements 13438defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Search the dictionary placing the result in edi. 13448defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateDictionaryLoad(masm, &miss, eax, ecx, edi, ebx, edi); 13458defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateFunctionTailCall(masm, argc, &miss); 13469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 13479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ bind(&miss); 1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) { 1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1353e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 1354e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 1355e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1356e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 1357e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13608defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (id == IC::kCallIC_Miss) { 13618defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ IncrementCounter(&Counters::call_miss, 1); 13628defd9ff6930b4e24729971a61cf7469daf119beSteve Block } else { 13638defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ IncrementCounter(&Counters::keyed_call_miss, 1); 13648defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 13658defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver of the function from the stack; 1 ~ return address. 1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Enter an internal frame. 1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ EnterInternalFrame(); 1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push the receiver and the name of the function. 1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(edx); 1374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(ecx); 1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call the entry. 1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CEntryStub stub(1); 1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, Immediate(2)); 13797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(ebx, Immediate(ExternalReference(IC_Utility(id)))); 1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CallStub(&stub); 1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move result to edi and exit the internal frame. 1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edi, eax); 1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LeaveInternalFrame(); 1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the receiver is a global object of some sort. 13878defd9ff6930b4e24729971a61cf7469daf119beSteve Block // This can happen only for regular CallIC but not KeyedCallIC. 13888defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (id == IC::kCallIC_Miss) { 13898defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label invoke, global; 13908defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); // receiver 13918defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ test(edx, Immediate(kSmiTagMask)); 13928defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(zero, &invoke, not_taken); 13938defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); 13948defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 13958defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ cmp(ebx, JS_GLOBAL_OBJECT_TYPE); 13968defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(equal, &global); 13978defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ cmp(ebx, JS_BUILTINS_OBJECT_TYPE); 13988defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(not_equal, &invoke); 13998defd9ff6930b4e24729971a61cf7469daf119beSteve Block 14008defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Patch the receiver on the stack. 14018defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ bind(&global); 14028defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 14038defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 14048defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ bind(&invoke); 14058defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the function. 1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount actual(argc); 1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeFunction(edi, actual, JUMP_FUNCTION); 1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { 14147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------- S t a t e ------------- 14157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ecx : name 14167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[0] : return address 14177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc - n) * 4] : arg[n] (zero-based) 14187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ... 14197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc + 1) * 4] : receiver 14207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------------------------------- 14217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Get the receiver of the function from the stack; 1 ~ return address. 14237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 14249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC); 14257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateMiss(masm, argc); 14267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 14277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid CallIC::GenerateNormal(MacroAssembler* masm, int argc) { 14309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // ----------- S t a t e ------------- 14319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- ecx : name 14329dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- esp[0] : return address 14339dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- esp[(argc - n) * 4] : arg[n] (zero-based) 14349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- ... 14359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- esp[(argc + 1) * 4] : receiver 14369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // ----------------------------------- 14379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 14389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateCallNormal(masm, argc); 14397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateMiss(masm, argc); 14407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 14417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid CallIC::GenerateMiss(MacroAssembler* masm, int argc) { 14449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // ----------- S t a t e ------------- 14459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- ecx : name 14469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- esp[0] : return address 14479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- esp[(argc - n) * 4] : arg[n] (zero-based) 14489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- ... 14499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- esp[(argc + 1) * 4] : receiver 14509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // ----------------------------------- 14519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 14527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateCallMiss(masm, argc, IC::kCallIC_Miss); 14537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 14547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { 14577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------- S t a t e ------------- 14587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ecx : name 14597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[0] : return address 14607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc - n) * 4] : arg[n] (zero-based) 14617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ... 14627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc + 1) * 4] : receiver 14637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------------------------------- 14647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Get the receiver of the function from the stack; 1 ~ return address. 14667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 14677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label do_call, slow_call, slow_load, slow_reload_receiver; 14697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label check_number_dictionary, check_string, lookup_monomorphic_cache; 14707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_smi, index_string; 14717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the key is a smi. 14737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test(ecx, Immediate(kSmiTagMask)); 14747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(not_zero, &check_string, not_taken); 14757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_smi); 14777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Now the key is known to be a smi. This place is also jumped to from 14787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // where a numeric string is converted to a smi. 14797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14808defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateKeyedLoadReceiverCheck( 14818defd9ff6930b4e24729971a61cf7469daf119beSteve Block masm, edx, eax, Map::kHasIndexedInterceptor, &slow_call); 14827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateFastArrayLoad( 14849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen masm, edx, ecx, eax, edi, &check_number_dictionary, &slow_load); 14857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ IncrementCounter(&Counters::keyed_call_generic_smi_fast, 1); 14867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&do_call); 14887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // receiver in edx is not used after this point. 14897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ecx: key 14907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // edi: function 14918defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateFunctionTailCall(masm, argc, &slow_call); 14927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&check_number_dictionary); 14947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // eax: elements 14957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ecx: smi key 14967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check whether the elements is a number dictionary. 14977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ CheckMap(eax, Factory::hash_table_map(), &slow_load, true); 14987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(ebx, ecx); 14997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ SmiUntag(ebx); 15007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ebx: untagged index 15017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Receiver in edx will be clobbered, need to reload it on miss. 15029dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateNumberDictionaryLoad( 15039dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen masm, &slow_reload_receiver, eax, ecx, ebx, edx, edi, edi); 15047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ IncrementCounter(&Counters::keyed_call_generic_smi_dict, 1); 15057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&do_call); 15067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 15077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&slow_reload_receiver); 15087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 15097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 15107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&slow_load); 15117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // This branch is taken when calling KeyedCallIC_Miss is neither required 15127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // nor beneficial. 15137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ IncrementCounter(&Counters::keyed_call_generic_slow_load, 1); 15147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ EnterInternalFrame(); 15157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(ecx); // save the key 15167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(edx); // pass the receiver 15177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(ecx); // pass the key 15187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ CallRuntime(Runtime::kKeyedGetProperty, 2); 15197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(ecx); // restore the key 15207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LeaveInternalFrame(); 15217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(edi, eax); 15227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&do_call); 15237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 15247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&check_string); 15257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateKeyStringCheck(masm, ecx, eax, ebx, &index_string, &slow_call); 15267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 15277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // The key is known to be a symbol. 15287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // If the receiver is a regular JS object with slow properties then do 15297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // a quick inline probe of the receiver's dictionary. 15307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Otherwise do the monomorphic cache probe. 15318defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateKeyedLoadReceiverCheck( 15328defd9ff6930b4e24729971a61cf7469daf119beSteve Block masm, edx, eax, Map::kHasNamedInterceptor, &lookup_monomorphic_cache); 15337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 15347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset)); 15358defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ CheckMap(ebx, Factory::hash_table_map(), &lookup_monomorphic_cache, true); 15367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 15378defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateDictionaryLoad(masm, &slow_load, ebx, ecx, eax, edi, edi); 15387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ IncrementCounter(&Counters::keyed_call_generic_lookup_dict, 1); 15397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&do_call); 15407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 15417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&lookup_monomorphic_cache); 15427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ IncrementCounter(&Counters::keyed_call_generic_lookup_cache, 1); 15439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC); 15447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Fall through on miss. 15457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 15467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&slow_call); 15477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // This branch is taken if: 15487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // - the receiver requires boxing or access check, 15497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // - the key is neither smi nor symbol, 15507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // - the value loaded is not a function, 15517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // - there is hope that the runtime will create a monomorphic call stub 15527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // that will get fetched next time. 15537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ IncrementCounter(&Counters::keyed_call_generic_slow, 1); 15547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateMiss(masm, argc); 15557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 15567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_string); 15579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateIndexFromHash(masm, ecx, ebx); 15589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Now jump to the place where smi keys are handled. 15599dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ jmp(&index_smi); 15607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 15617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 15627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 15637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { 15649dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // ----------- S t a t e ------------- 15659dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- ecx : name 15669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- esp[0] : return address 15679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- esp[(argc - n) * 4] : arg[n] (zero-based) 15689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- ... 15699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- esp[(argc + 1) * 4] : receiver 15709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // ----------------------------------- 15719dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 15729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateCallNormal(masm, argc); 15737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateMiss(masm, argc); 15747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 15757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 15767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 15777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) { 15789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // ----------- S t a t e ------------- 15799dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- ecx : name 15809dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- esp[0] : return address 15819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- esp[(argc - n) * 4] : arg[n] (zero-based) 15829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- ... 15839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // -- esp[(argc + 1) * 4] : receiver 15849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // ----------------------------------- 15859dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 15867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss); 15877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 15887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 15897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Defined in ic.cc. 1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* LoadIC_Miss(Arguments args); 1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateMegamorphic(MacroAssembler* masm) { 1594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1595402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 1597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the stub cache. 1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, 1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NOT_IN_LOOP, 1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MONOMORPHIC); 1604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCache::GenerateProbe(masm, flags, eax, ecx, ebx, edx); 1605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cache miss: Jump to runtime. 1607402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateMiss(masm); 1608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateNormal(MacroAssembler* masm) { 1612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1613402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 16178defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label miss; 1618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16198defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateStringDictionaryReceiverCheck(masm, eax, edx, ebx, &miss); 1620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16218defd9ff6930b4e24729971a61cf7469daf119beSteve Block // edx: elements 1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Search the dictionary placing the result in eax. 16238defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateDictionaryLoad(masm, &miss, edx, ecx, edi, ebx, eax); 1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 1625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Cache miss: Jump to runtime. 1627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 1628402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateMiss(masm); 1629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateMiss(MacroAssembler* masm) { 1633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1634402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 1635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 1636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16398defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ IncrementCounter(&Counters::load_miss, 1); 16408defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); 1642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(eax); // receiver 1643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); // name 1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); // return address 1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform tail call to the entry. 16476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss)); 16486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(ref, 2, 1); 1649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// One byte opcode for test eax,0xXXXXXXXX. 1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const byte kTestEaxByte = 0xA9; 1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { 1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The address of the instruction following the call. 1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address test_instruction_address = 1658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block address + Assembler::kCallTargetAddressOffset; 1659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the instruction following the call is not a test eax, nothing 1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // was inlined. 1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*test_instruction_address != kTestEaxByte) return false; 1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address delta_address = test_instruction_address + 1; 1664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The delta to the start of the map check instruction. 1665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int delta = *reinterpret_cast<int*>(delta_address); 1666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The map address is the last 4 bytes of the 7-byte 1668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // operand-immediate compare instruction, so we add 3 to get the 1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // offset to the last 4 bytes. 1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address map_address = test_instruction_address + delta + 3; 1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *(reinterpret_cast<Object**>(map_address)) = map; 1672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The offset is in the last 4 bytes of a six byte 1674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // memory-to-register move instruction, so we add 2 to get the 1675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // offset to the last 4 bytes. 1676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address offset_address = 1677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block test_instruction_address + delta + kOffsetToLoadInstruction + 2; 1678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; 1679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 1680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 168350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsenbool StoreIC::PatchInlinedStore(Address address, Object* map, int offset) { 168450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // The address of the instruction following the call. 168550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen Address test_instruction_address = 168650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen address + Assembler::kCallTargetAddressOffset; 168750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 168850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // If the instruction following the call is not a test eax, nothing 168950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // was inlined. 169050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen if (*test_instruction_address != kTestEaxByte) return false; 169150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 169250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // Extract the encoded deltas from the test eax instruction. 169350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen Address encoded_offsets_address = test_instruction_address + 1; 169450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen int encoded_offsets = *reinterpret_cast<int*>(encoded_offsets_address); 169550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen int delta_to_map_check = -(encoded_offsets & 0xFFFF); 169650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen int delta_to_record_write = encoded_offsets >> 16; 169750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 169850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // Patch the map to check. The map address is the last 4 bytes of 169950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // the 7-byte operand-immediate compare instruction. 170050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen Address map_check_address = test_instruction_address + delta_to_map_check; 170150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen Address map_address = map_check_address + 3; 170250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen *(reinterpret_cast<Object**>(map_address)) = map; 170350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 170450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // Patch the offset in the store instruction. The offset is in the 170550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // last 4 bytes of a six byte register-to-memory move instruction. 170650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen Address offset_address = 170750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen map_check_address + StoreIC::kOffsetToStoreInstruction + 2; 170850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // The offset should have initial value (kMaxInt - 1), cleared value 170950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // (-1) or we should be clearing the inlined version. 171050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt - 1 || 171150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen *reinterpret_cast<int*>(offset_address) == -1 || 171250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen (offset == 0 && map == Heap::null_value())); 171350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; 171450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 171550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // Patch the offset in the write-barrier code. The offset is the 171650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // last 4 bytes of a six byte lea instruction. 171750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen offset_address = map_check_address + delta_to_record_write + 2; 171850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // The offset should have initial value (kMaxInt), cleared value 171950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // (-1) or we should be clearing the inlined version. 172050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt || 172150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen *reinterpret_cast<int*>(offset_address) == -1 || 172250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen (offset == 0 && map == Heap::null_value())); 172350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; 172450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 172550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen return true; 172650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen} 172750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 172850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 1729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool PatchInlinedMapCheck(Address address, Object* map) { 1730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address test_instruction_address = 1731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block address + Assembler::kCallTargetAddressOffset; 1732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The keyed load has a fast inlined case if the IC call instruction 1733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is immediately followed by a test instruction. 1734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*test_instruction_address != kTestEaxByte) return false; 1735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fetch the offset from the test instruction to the map cmp 1737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // instruction. This offset is stored in the last 4 bytes of the 5 1738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // byte test instruction. 1739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address delta_address = test_instruction_address + 1; 1740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int delta = *reinterpret_cast<int*>(delta_address); 1741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the map address. The map address is in the last 4 bytes 1742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // of the 7-byte operand-immediate compare instruction, so we add 3 1743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to the offset to get the map address. 1744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address map_address = test_instruction_address + delta + 3; 1745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the map check. 1746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *(reinterpret_cast<Object**>(map_address)) = map; 1747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 1748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool KeyedLoadIC::PatchInlinedLoad(Address address, Object* map) { 1752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return PatchInlinedMapCheck(address, map); 1753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool KeyedStoreIC::PatchInlinedStore(Address address, Object* map) { 1757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return PatchInlinedMapCheck(address, map); 1758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Defined in ic.cc. 1762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadIC_Miss(Arguments args); 1763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { 1766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1767402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 1768402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 1769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 17728defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ IncrementCounter(&Counters::keyed_load_miss, 1); 17738defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1774402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(ebx); 1775402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(edx); // receiver 1776402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(eax); // name 1777402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(ebx); // return address 1778402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1779402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Perform tail call to the entry. 17806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss)); 17816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(ref, 2, 1); 1782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1785402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { 1786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1787402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 1788402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 1789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); 1793402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(edx); // receiver 1794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(eax); // name 1795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); // return address 1796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform tail call to the entry. 17986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 1799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StoreIC::GenerateMegamorphic(MacroAssembler* masm) { 1803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 1805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 18064515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- edx : receiver 1807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, 1811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NOT_IN_LOOP, 1812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MONOMORPHIC); 1813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg); 1814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cache miss: Jump to runtime. 18164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke GenerateMiss(masm); 1817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 18204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid StoreIC::GenerateMiss(MacroAssembler* masm) { 1821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 1823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 18244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- edx : receiver 1825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); 18294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(edx); 1830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); 1831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(eax); 1832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); 1833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform tail call to the entry. 18356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_Miss)); 18366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(ref, 3, 1); 18376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 18386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 184050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen// The offset from the inlined patch site to the start of the inlined 184150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen// store instruction. It is 7 bytes (test reg, imm) plus 6 bytes (jne 184250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen// slow_label). 184350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsenconst int StoreIC::kOffsetToStoreInstruction = 13; 184450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 184550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen 18466ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid StoreIC::GenerateArrayLength(MacroAssembler* masm) { 18476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 18486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- eax : value 18496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : name 18506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- edx : receiver 18516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[0] : return address 18526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 18536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 18546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // This accepts as a receiver anything JSObject::SetElementsLength accepts 18556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // (currently anything except for external and pixel arrays which means 18566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // anything with elements of FixedArray type.), but currently is restricted 18576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // to JSArray. 18586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Value must be a number, but only smis are accepted as the most common case. 18596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss; 18616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register receiver = edx; 18636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register value = eax; 18646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch = ebx; 18656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the receiver isn't a smi. 18676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(receiver, Immediate(kSmiTagMask)); 18686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(zero, &miss, not_taken); 18696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the object is a JS array. 18716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); 18726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_equal, &miss, not_taken); 18736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that elements are FixedArray. 18756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(scratch, FieldOperand(receiver, JSArray::kElementsOffset)); 18766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch); 18776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_equal, &miss, not_taken); 18786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that value is a smi. 18806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(value, Immediate(kSmiTagMask)); 18816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_zero, &miss, not_taken); 18826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Prepare tail call to StoreIC_ArrayLength. 18846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(scratch); 18856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(receiver); 18866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(value); 18876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(scratch); // return address 18886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_ArrayLength)); 18906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(ref, 2, 1); 18916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss); 18936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GenerateMiss(masm); 1895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 18988defd9ff6930b4e24729971a61cf7469daf119beSteve Blockvoid StoreIC::GenerateNormal(MacroAssembler* masm) { 18998defd9ff6930b4e24729971a61cf7469daf119beSteve Block // ----------- S t a t e ------------- 19008defd9ff6930b4e24729971a61cf7469daf119beSteve Block // -- eax : value 19018defd9ff6930b4e24729971a61cf7469daf119beSteve Block // -- ecx : name 19028defd9ff6930b4e24729971a61cf7469daf119beSteve Block // -- edx : receiver 19038defd9ff6930b4e24729971a61cf7469daf119beSteve Block // -- esp[0] : return address 19048defd9ff6930b4e24729971a61cf7469daf119beSteve Block // ----------------------------------- 19058defd9ff6930b4e24729971a61cf7469daf119beSteve Block 19068defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label miss, restore_miss; 19078defd9ff6930b4e24729971a61cf7469daf119beSteve Block 19088defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateStringDictionaryReceiverCheck(masm, edx, ebx, edi, &miss); 19098defd9ff6930b4e24729971a61cf7469daf119beSteve Block 19108defd9ff6930b4e24729971a61cf7469daf119beSteve Block // A lot of registers are needed for storing to slow case 19118defd9ff6930b4e24729971a61cf7469daf119beSteve Block // objects. Push and restore receiver but rely on 19128defd9ff6930b4e24729971a61cf7469daf119beSteve Block // GenerateDictionaryStore preserving the value and name. 19138defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ push(edx); 19148defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateDictionaryStore(masm, &restore_miss, ebx, ecx, eax, edx, edi); 19158defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ Drop(1); 19168defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ IncrementCounter(&Counters::store_normal_hit, 1); 19178defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ ret(0); 19188defd9ff6930b4e24729971a61cf7469daf119beSteve Block 19198defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ bind(&restore_miss); 19208defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ pop(edx); 19218defd9ff6930b4e24729971a61cf7469daf119beSteve Block 19228defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ bind(&miss); 19238defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ IncrementCounter(&Counters::store_normal_miss, 1); 19248defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateMiss(masm); 19258defd9ff6930b4e24729971a61cf7469daf119beSteve Block} 19268defd9ff6930b4e24729971a61cf7469daf119beSteve Block 19278defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Defined in ic.cc. 1929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedStoreIC_Miss(Arguments args); 1930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1931402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) { 1932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 19346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : key 19356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- edx : receiver 1936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 19396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(ebx); 19406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(edx); 1941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); 19426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(eax); 19436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(ebx); 1944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to runtime routine. 19466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallRuntime(Runtime::kSetProperty, 3, 1); 1947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1950402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { 1951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 19536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : key 19546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- edx : receiver 1955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 19586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(ebx); 19596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(edx); 1960402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(ecx); 19616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(eax); 19626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(ebx); 1963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to runtime routine. 19656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); 19666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(ref, 3, 1); 1967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 1970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 1973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_IA32 1975