ic-ia32.cc revision 7f4d5bd8c03935e2c0cd412e561b8fc5a6a880ae
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 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper function used to load a property from a dictionary backing storage. 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This function may return false negatives, so miss_label 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// must always call a backup property load that is complete. 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This function is safe to call if the receiver has fast properties, 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// or if name is not a symbol, and will jump to the miss_label in that case. 53e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkestatic void GenerateDictionaryLoad(MacroAssembler* masm, 54e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* miss_label, 55402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register receiver, 56402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register name, 57e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register r0, 58e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register r1, 59e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register r2, 607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result, 61e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DictionaryCheck check_dictionary) { 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Register use: 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 64402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // name - holds the name of the property and is unchanged. 65402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // receiver - holds the receiver and is unchanged. 66402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Scratch registers: 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0 - used to hold the property dictionary. 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 69402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // r1 - used for the index into the property dictionary 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2 - used to hold the capacity of the property dictionary. 727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // 737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // result - holds the result on exit. 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label done; 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for the absence of an interceptor. 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the map into r0. 79402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(r0, FieldOperand(receiver, JSObject::kMapOffset)); 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Bail out if the receiver has a named interceptor. 826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(FieldOperand(r0, Map::kBitFieldOffset), 836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Immediate(1 << Map::kHasNamedInterceptor)); 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, miss_label, not_taken); 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Bail out if we have a JS global proxy object. 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(r0, FieldOperand(r0, Map::kInstanceTypeOffset)); 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, JS_GLOBAL_PROXY_TYPE); 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, miss_label, not_taken); 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Possible work-around for http://crbug.com/16276. 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, JS_GLOBAL_OBJECT_TYPE); 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, miss_label, not_taken); 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, JS_BUILTINS_OBJECT_TYPE); 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, miss_label, not_taken); 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 97e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Load properties array. 98402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(r0, FieldOperand(receiver, JSObject::kPropertiesOffset)); 99e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 100e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the properties array is a dictionary. 101e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (check_dictionary == CHECK_DICTIONARY) { 102e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(FieldOperand(r0, HeapObject::kMapOffset), 103e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Immediate(Factory::hash_table_map())); 104e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_equal, miss_label); 105e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the capacity mask. 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kCapacityOffset = 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StringDictionary::kHeaderSize + 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StringDictionary::kCapacityIndex * kPointerSize; 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, FieldOperand(r0, kCapacityOffset)); 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ shr(r2, kSmiTagSize); // convert smi to int 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ dec(r2); 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Generate an unrolled loop that performs a few probes before 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // giving up. Measurements done on Gmail indicate that 2 probes 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // cover ~93% of loads from dictionaries. 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kProbes = 4; 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kElementsStartOffset = 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StringDictionary::kHeaderSize + 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StringDictionary::kElementsStartIndex * kPointerSize; 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < kProbes; i++) { 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the masked index: (hash + i + i * i) & mask. 124d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r1, FieldOperand(name, String::kHashFieldOffset)); 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ shr(r1, String::kHashShift); 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (i > 0) { 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(Operand(r1), Immediate(StringDictionary::GetProbeOffset(i))); 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(r1, Operand(r2)); 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Scale the index by multiplying by the entry size. 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(StringDictionary::kEntrySize == 3); 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(r1, Operand(r1, r1, times_2, 0)); // r1 = r1 * 3 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the key is identical to the name. 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(name, 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand(r0, r1, times_4, kElementsStartOffset - kHeapObjectTag)); 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (i != kProbes - 1) { 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &done, taken); 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, miss_label, not_taken); 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the value is a normal property. 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&done); 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(Operand(r0, r1, times_4, kDetailsOffset - kHeapObjectTag), 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, miss_label, not_taken); 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the value at the masked, scaled index. 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kValueOffset = kElementsStartOffset + kPointerSize; 1547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(result, Operand(r0, r1, times_4, kValueOffset - kHeapObjectTag)); 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1586ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void GenerateNumberDictionaryLoad(MacroAssembler* masm, 1596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* miss, 1606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register elements, 1616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register key, 1626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register r0, 1636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register r1, 1647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register r2, 1657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result) { 1666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Register use: 1676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 1686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // elements - holds the slow-case elements of the receiver and is unchanged. 1696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 1707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // key - holds the smi key on entry and is unchanged. 1716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 1726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Scratch registers: 1736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 1746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // r0 - holds the untagged key on entry and holds the hash once computed. 1756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 1766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // r1 - used to hold the capacity mask of the dictionary 1776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 1786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // r2 - used for the index into the dictionary. 1797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // 1807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // result - holds the result on exit if the load succeeds and we fall through. 1817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label done; 1836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Compute the hash code from the untagged key. This must be kept in sync 1856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // with ComputeIntegerHash in utils.h. 1866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 1876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // hash = ~hash + (hash << 15); 1886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r1, r0); 1896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ not_(r0); 1906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ shl(r1, 15); 1916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ add(r0, Operand(r1)); 1926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // hash = hash ^ (hash >> 12); 1936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r1, r0); 1946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ shr(r1, 12); 1956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ xor_(r0, Operand(r1)); 1966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // hash = hash + (hash << 2); 1976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ lea(r0, Operand(r0, r0, times_4, 0)); 1986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // hash = hash ^ (hash >> 4); 1996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r1, r0); 2006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ shr(r1, 4); 2016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ xor_(r0, Operand(r1)); 2026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // hash = hash * 2057; 2036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ imul(r0, r0, 2057); 2046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // hash = hash ^ (hash >> 16); 2056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r1, r0); 2066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ shr(r1, 16); 2076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ xor_(r0, Operand(r1)); 2086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Compute capacity mask. 2106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r1, FieldOperand(elements, NumberDictionary::kCapacityOffset)); 2116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ shr(r1, kSmiTagSize); // convert smi to int 2126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ dec(r1); 2136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Generate an unrolled loop that performs a few probes before giving up. 2156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kProbes = 4; 2166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (int i = 0; i < kProbes; i++) { 2176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Use r2 for index calculations and keep the hash intact in r0. 2186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r2, r0); 2196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Compute the masked index: (hash + i + i * i) & mask. 2206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (i > 0) { 2216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ add(Operand(r2), Immediate(NumberDictionary::GetProbeOffset(i))); 2226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ and_(r2, Operand(r1)); 2246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Scale the index by multiplying by the entry size. 2266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(NumberDictionary::kEntrySize == 3); 2276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 2286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check if the key matches. 2306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(key, FieldOperand(elements, 2316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block r2, 2326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block times_pointer_size, 2336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NumberDictionary::kElementsStartOffset)); 2346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (i != (kProbes - 1)) { 2356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(equal, &done, taken); 2366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 2376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_equal, miss, not_taken); 2386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&done); 2426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the value is a normal propety. 2436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kDetailsOffset = 2446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NumberDictionary::kElementsStartOffset + 2 * kPointerSize; 2456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT_EQ(NORMAL, 0); 2466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), 2476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); 2486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_zero, miss); 2496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the value at the masked, scaled index. 2516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kValueOffset = 2526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NumberDictionary::kElementsStartOffset + kPointerSize; 2537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); 2546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 2556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The offset from the inlined patch site to the start of the 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// inlined load instruction. It is 7 bytes (test eax, imm) plus 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6 bytes (jne slow_label). 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int LoadIC::kOffsetToLoadInstruction = 13; 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateArrayLength(MacroAssembler* masm) { 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 265402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadArrayLength(masm, eax, edx, &miss); 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateStringLength(MacroAssembler* masm) { 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 279402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 285402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu StubCompiler::GenerateLoadStringLength(masm, eax, edx, ebx, &miss); 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) { 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 293402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadFunctionPrototype(masm, eax, edx, ebx, &miss); 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Checks the receiver for special cases (value type, slow case bits). 3067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Falls through for regular JS object. 3077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, 3087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register receiver, 3097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register r0, 3107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label* slow) { 3117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Register use: 3127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // receiver - holds the receiver and is unchanged. 3137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Scratch registers: 3147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // r0 - used to hold the map of the receiver. 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object isn't a smi. 3177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test(receiver, Immediate(kSmiTagMask)); 3187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(zero, slow, not_taken); 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the map of the receiver. 3217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); 322d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 323d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Check bit field. 3247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test_b(FieldOperand(r0, Map::kBitFieldOffset), 3257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch KeyedLoadIC::kSlowCaseBitFieldMask); 3267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(not_zero, slow, not_taken); 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is some kind of JS object EXCEPT JS Value type. 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // In the case that the object is a value-wrapper object, 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // we enter the runtime system to make sure that indexing 3307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // into string objects works as intended. 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); 3327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 3337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ CmpInstanceType(r0, JS_OBJECT_TYPE); 3347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(below, slow, not_taken); 3357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 3367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 3377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 3387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Loads an indexed element from a fast case array. 3397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void GenerateFastArrayLoad(MacroAssembler* masm, 3407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register receiver, 3417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register key, 3427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch, 3437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result, 3447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label* not_fast_array, 3457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label* out_of_range) { 3467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Register use: 3477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // receiver - holds the receiver and is unchanged. 3487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // key - holds the key and is unchanged (must be a smi). 3497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Scratch registers: 3507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // scratch - used to hold elements of the receiver and the loaded value. 3517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // result - holds the result on exit if the load succeeds and 3527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // we fall through. 3537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 3547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(scratch, FieldOperand(receiver, JSObject::kElementsOffset)); 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is in fast mode (not dictionary). 3567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ CheckMap(scratch, Factory::fixed_array_map(), not_fast_array, true); 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the key (index) is within bounds. 3587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ cmp(key, FieldOperand(scratch, FixedArray::kLengthOffset)); 3597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(above_equal, out_of_range); 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fast case: Do the load. 3617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0)); 3627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(scratch, FieldOperand(scratch, key, times_2, FixedArray::kHeaderSize)); 3637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ cmp(Operand(scratch), Immediate(Factory::the_hole_value())); 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // In case the loaded value is the_hole we have to consult GetProperty 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to ensure the prototype chain is searched. 3667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(equal, out_of_range); 3677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (!result.is(scratch)) { 3687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(result, scratch); 3697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 3707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 3717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 3727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 3737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Checks whether a key is an array index string or a symbol string. 3747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Falls through if a key is a symbol. 3757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void GenerateKeyStringCheck(MacroAssembler* masm, 3767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register key, 3777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register map, 3787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register hash, 3797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label* index_string, 3807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label* not_symbol) { 3817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Register use: 3827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // key - holds the key and is unchanged. Assumed to be non-smi. 3837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Scratch registers: 3847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // map - used to hold the map of the key. 3857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // hash - used to hold the hash of the key. 3867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ CmpObjectType(key, FIRST_NONSTRING_TYPE, map); 3877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(above_equal, not_symbol); 3887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 3897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Is the string an array index, with cached numeric value? 3907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(hash, FieldOperand(key, String::kHashFieldOffset)); 3917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test(hash, Immediate(String::kContainsCachedArrayIndexMask)); 3927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(zero, index_string, not_taken); 3937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 3947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Is the string a symbol? 3957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(kSymbolTag != 0); 3967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsSymbolMask); 3977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(zero, not_symbol, not_taken); 3987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 3997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 4007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 4017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Picks out an array index from the hash field. 4027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// The generated code never falls through. 4037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void GenerateIndexFromHash(MacroAssembler* masm, 4047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register key, 4057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register hash, 4067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label* index_smi) { 4077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Register use: 4087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // key - holds the overwritten key on exit. 4097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // hash - holds the key's hash. Clobbered. 4107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 4117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // The assert checks that the constants for the maximum number of digits 4127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // for an array index cached in the hash field and the number of bits 4137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // reserved for it does not conflict. 4147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < 4157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch (1 << String::kArrayIndexValueBits)); 4167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // We want the smi-tagged index in key. kArrayIndexValueMask has zeros in 4177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // the low kHashShift bits. 4187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // key: string key 4197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ebx: hash field. 4207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(String::kHashShift >= kSmiTagSize); 4217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ and_(hash, String::kArrayIndexValueMask); 4227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ shr(hash, String::kHashShift - kSmiTagSize); 4237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Here we actually clobber the key which will be used if calling into 4247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // runtime later. However as the new key is the numeric value of a string key 4257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // there is no difference in using either key. 4267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(key, hash); 4277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Now jump to the place where smi keys are handled. 4287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(index_smi); 4297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 4307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 4317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 4327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 4337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------- S t a t e ------------- 4347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- eax : key 4357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- edx : receiver 4367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[0] : return address 4377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------------------------------- 4387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label slow, check_string, index_smi, index_string; 4397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label check_pixel_array, probe_dictionary, check_number_dictionary; 4407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 4417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateKeyedLoadReceiverCheck(masm, edx, ecx, &slow); 4427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 4437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the key is a smi. 4447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test(eax, Immediate(kSmiTagMask)); 4457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(not_zero, &check_string, not_taken); 4467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_smi); 4477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Now the key is known to be a smi. This place is also jumped to from 4487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // where a numeric string is converted to a smi. 4497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 4507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateFastArrayLoad(masm, 4517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch edx, 4527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch eax, 4537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ecx, 4547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch eax, 4557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &check_pixel_array, 4567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &slow); 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&check_pixel_array); 461402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Check whether the elements is a pixel array. 462402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // edx: receiver 463402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // eax: key 464402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ecx: elements 4657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(ebx, eax); 4667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ SmiUntag(ebx); 4676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CheckMap(ecx, Factory::pixel_array_map(), &check_number_dictionary, true); 468402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(ebx, FieldOperand(ecx, PixelArray::kLengthOffset)); 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &slow); 470402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, FieldOperand(ecx, PixelArray::kExternalPointerOffset)); 471402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(eax, Operand(eax, ebx, times_1, 0)); 472402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ SmiTag(eax); 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&check_number_dictionary); 4766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check whether the elements is a number dictionary. 4776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver 4786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ebx: untagged index 4796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // eax: key 4806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: elements 4816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CheckMap(ecx, Factory::hash_table_map(), &slow, true); 4826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label slow_pop_receiver; 4836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Push receiver on the stack to free up a register for the dictionary 4846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // probing. 4856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(edx); 4866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GenerateNumberDictionaryLoad(masm, 4876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block &slow_pop_receiver, 4886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ecx, 4896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block eax, 4906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ebx, 4916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block edx, 4927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch edi, 4937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch eax); 4946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Pop receiver before returning. 4956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(edx); 4966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret(0); 4976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 4986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&slow_pop_receiver); 4996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Pop the receiver from the stack and jump to runtime. 5006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(edx); 5016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&slow); 503402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Slow case: jump to runtime. 504402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // edx: receiver 505402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // eax: key 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); 507402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateRuntimeGetProperty(masm); 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&check_string); 5107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateKeyStringCheck(masm, eax, ecx, ebx, &index_string, &slow); 511e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 512e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // If the receiver is a fast-case object, check the keyed lookup 513402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // cache. Otherwise probe the dictionary. 514402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset)); 515e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 516e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Immediate(Factory::hash_table_map())); 517e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, &probe_dictionary); 518e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 519e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Load the map of the receiver, compute the keyed lookup cache hash 520e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // based on 32 bits of the map pointer and the string hash. 521402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); 522402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, ebx); 523402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ shr(ecx, KeyedLookupCache::kMapHashShift); 524402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(edi, FieldOperand(eax, String::kHashFieldOffset)); 525402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ shr(edi, String::kHashShift); 526402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ xor_(ecx, Operand(edi)); 527402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ and_(ecx, KeyedLookupCache::kCapacityMask); 528e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 529e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Load the key (consisting of map and symbol) from the cache and 530e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // check for match. 531e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ExternalReference cache_keys 532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke = ExternalReference::keyed_lookup_cache_keys(); 533402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(edi, ecx); 534e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ shl(edi, kPointerSizeLog2 + 1); 535e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys)); 536e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_equal, &slow); 537e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ add(Operand(edi), Immediate(kPointerSize)); 538402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(eax, Operand::StaticArray(edi, times_1, cache_keys)); 539e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_equal, &slow); 540e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 541e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Get field offset and check that it is an in-object property. 542402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // edx : receiver 543402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ebx : receiver's map 544402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // eax : key 545402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ecx : lookup cache index 546e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ExternalReference cache_field_offsets 547e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke = ExternalReference::keyed_lookup_cache_field_offsets(); 548402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(edi, 549402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Operand::StaticArray(ecx, times_pointer_size, cache_field_offsets)); 550402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(ecx, FieldOperand(ebx, Map::kInObjectPropertiesOffset)); 5517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ sub(edi, Operand(ecx)); 552e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(above_equal, &slow); 553e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 554e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Load in-object property. 555402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset)); 556402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ add(ecx, Operand(edi)); 557402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, FieldOperand(edx, ecx, times_pointer_size, 0)); 5587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ IncrementCounter(&Counters::keyed_load_generic_lookup_cache, 1); 559e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ret(0); 560e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 561e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Do a quick inline probe of the receiver's dictionary, if it 562e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // exists. 563e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&probe_dictionary); 564e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke GenerateDictionaryLoad(masm, 565e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke &slow, 566e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke edx, 567e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke eax, 568402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ebx, 569402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ecx, 570402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu edi, 5717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch eax, 572e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DICTIONARY_CHECK_DONE); 573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 575e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&index_string); 5777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateIndexFromHash(masm, eax, ebx, &index_smi); 578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 581e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid KeyedLoadIC::GenerateString(MacroAssembler* masm) { 582e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------- S t a t e ------------- 5836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- eax : key (index) 584402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 585e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 586e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------------------------------- 5876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss; 5886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label index_out_of_range; 5896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register receiver = edx; 5916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register index = eax; 5927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch1 = ebx; 5937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch2 = ecx; 5947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = eax; 5957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 5967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharAtGenerator char_at_generator(receiver, 5977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch index, 5987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch1, 5997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch2, 6007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch result, 6017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &miss, // When not a string. 6027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &miss, // When not a number. 6037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &index_out_of_range, 6047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch STRING_INDEX_IS_ARRAY_INDEX); 6057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch char_at_generator.GenerateFast(masm); 6067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ ret(0); 6077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 6087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ICRuntimeCallHelper call_helper; 6097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch char_at_generator.GenerateSlow(masm, call_helper); 610e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 6116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&index_out_of_range); 6126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Set(eax, Immediate(Factory::undefined_value())); 6136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret(0); 614e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 615e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&miss); 616e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke GenerateMiss(masm); 617e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 619e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 6203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm, 6213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ExternalArrayType array_type) { 6223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ----------- S t a t e ------------- 623402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 624402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 6253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // -- esp[0] : return address 6263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ----------------------------------- 6273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label slow, failed_allocation; 6283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 6293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the object isn't a smi. 630402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ test(edx, Immediate(kSmiTagMask)); 6313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(zero, &slow, not_taken); 6323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 6333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the key is a smi. 6343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ test(eax, Immediate(kSmiTagMask)); 6353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_zero, &slow, not_taken); 6363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 6373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Get the map of the receiver. 638402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 6393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the receiver does not require access checks. We need 6403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // to check this explicitly since this generic stub does not perform 6413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // map checks. 6427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 6437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1 << Map::kIsAccessCheckNeeded); 6443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_zero, &slow, not_taken); 6453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 646402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CmpInstanceType(ecx, JS_OBJECT_TYPE); 6473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, &slow, not_taken); 6483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 6493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the elements array is the appropriate type of 6503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ExternalArray. 651402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); 6523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Handle<Map> map(Heap::MapForExternalArrayType(array_type)); 653402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 6543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Immediate(map)); 6553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, &slow, not_taken); 6563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 657402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // eax: key, known to be a smi. 658402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // edx: receiver, known to be a JSObject. 659402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ebx: elements object, known to be an external array. 6603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the index is in range. 661402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, eax); 662402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ SmiUntag(ecx); // Untag the index. 663402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset)); 6643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Unsigned comparison catches both negative and too-large values. 6653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(above_equal, &slow); 6663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 667402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset)); 668402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ebx: base pointer of external storage 6693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block switch (array_type) { 6703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalByteArray: 671402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movsx_b(ecx, Operand(ebx, ecx, times_1, 0)); 6723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 6733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedByteArray: 674402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(ecx, Operand(ebx, ecx, times_1, 0)); 6753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 6763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalShortArray: 677402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movsx_w(ecx, Operand(ebx, ecx, times_2, 0)); 6783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 6793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedShortArray: 680402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_w(ecx, Operand(ebx, ecx, times_2, 0)); 6813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 6823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalIntArray: 6833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedIntArray: 684402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, Operand(ebx, ecx, times_4, 0)); 6853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 6863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalFloatArray: 687402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ fld_s(Operand(ebx, ecx, times_4, 0)); 6883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 6893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block default: 6903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block UNREACHABLE(); 6913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 6923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 6933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 6943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // For integer array types: 695402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ecx: value 6963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // For floating-point array type: 6973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // FP(0): value 6983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 6993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (array_type == kExternalIntArray || 7003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block array_type == kExternalUnsignedIntArray) { 7013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // For the Int and UnsignedInt array types, we need to see whether 7023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // the value can be represented in a Smi. If not, we need to convert 7033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // it to a HeapNumber. 7043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label box_int; 7053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (array_type == kExternalIntArray) { 706402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(ecx, 0xC0000000); 707402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ j(sign, &box_int); 7083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 7093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT_EQ(array_type, kExternalUnsignedIntArray); 7103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // The test is different for unsigned int values. Since we need 711402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // the value to be in the range of a positive smi, we can't 7123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // handle either of the top two bits being set in the value. 713402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ test(ecx, Immediate(0xC0000000)); 7143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_zero, &box_int); 7153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 7163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 717402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, ecx); 718402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ SmiTag(eax); 7193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ret(0); 7203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&box_int); 7223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Allocate a HeapNumber for the int and perform int-to-double 7243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // conversion. 7253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (array_type == kExternalIntArray) { 726402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(ecx); 7273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fild_s(Operand(esp, 0)); 728402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(ecx); 7293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 7303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(array_type == kExternalUnsignedIntArray); 7313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Need to zero-extend the value. 7323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // There's no fild variant for unsigned values, so zero-extend 7333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // to a 64-bit int manually. 7343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(Immediate(0)); 735402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(ecx); 7363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fild_d(Operand(esp, 0)); 737402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(ecx); 738402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(ecx); 7393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 7403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // FP(0): value 741402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); 7423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Set the value. 743402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, ecx); 7443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 7453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ret(0); 7463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (array_type == kExternalFloatArray) { 7473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // For the floating-point array type, we need to always allocate a 7483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // HeapNumber. 749402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); 7503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Set the value. 751402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, ecx); 7523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 7533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ret(0); 7543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 755402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, ecx); 756402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ SmiTag(eax); 7573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ret(0); 7583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 7593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If we fail allocation of the HeapNumber, we still have a value on 7613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // top of the FPU stack. Remove it. 7623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&failed_allocation); 7633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ffree(); 7643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fincstp(); 7653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Fall through to slow case. 7663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Slow case: Jump to runtime. 7683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&slow); 7693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1); 770402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateRuntimeGetProperty(masm); 771402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 772402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 773402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 774402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { 775402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------- S t a t e ------------- 776402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 777402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 778402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- esp[0] : return address 779402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------------------------------- 780402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label slow; 781402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 782402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Check that the receiver isn't a smi. 783402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ test(edx, Immediate(kSmiTagMask)); 784402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ j(zero, &slow, not_taken); 785402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 786402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Check that the key is a smi. 787402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ test(eax, Immediate(kSmiTagMask)); 788402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ j(not_zero, &slow, not_taken); 789402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 790402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Get the map of the receiver. 791402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 792402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 793402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Check that it has indexed interceptor and access checks 794402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // are not enabled for this object. 795402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(ecx, FieldOperand(ecx, Map::kBitFieldOffset)); 796402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ and_(Operand(ecx), Immediate(kSlowCaseBitFieldMask)); 797402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(Operand(ecx), Immediate(1 << Map::kHasIndexedInterceptor)); 798402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ j(not_zero, &slow, not_taken); 799402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 800402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Everything is fine, call runtime. 801402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(ecx); 802402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(edx); // receiver 803402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(eax); // key 804402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(ecx); // return address 805402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 806402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Perform tail call to the entry. 8076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference ref = ExternalReference( 8086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block IC_Utility(kKeyedLoadPropertyWithInterceptor)); 8096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(ref, 2, 1); 810402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 811402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ bind(&slow); 812402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateMiss(masm); 8133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 8143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { 817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 8196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : key 8206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- edx : receiver 821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label slow, fast, array, extra, check_pixel_array; 824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object isn't a smi. 826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(edx, Immediate(kSmiTagMask)); 827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &slow, not_taken); 828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the map from the receiver. 8296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); 830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver does not require access checks. We need 831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to do this because this generic stub does not perform map checks. 8327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test_b(FieldOperand(edi, Map::kBitFieldOffset), 8337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1 << Map::kIsAccessCheckNeeded); 834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &slow, not_taken); 835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the key is a smi. 8366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(ecx, Immediate(kSmiTagMask)); 837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &slow, not_taken); 8386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CmpInstanceType(edi, JS_ARRAY_TYPE); 839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &array); 840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is some kind of JS object. 8416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE); 8426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(below, &slow, not_taken); 843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Object case: Check key against length in the elements array. 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: value 846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edx: JSObject 8476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: key (a smi) 8486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is in fast mode (not dictionary). 8506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true); 8517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); 852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(below, &fast, taken); 853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Slow case: call runtime. 855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&slow); 856402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateRuntimeSetProperty(masm); 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check whether the elements is a pixel array. 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&check_pixel_array); 8606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // eax: value 8617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ecx: key (a smi) 8626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver 8636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edi: elements array 8646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CheckMap(edi, Factory::pixel_array_map(), &slow, true); 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the value is a smi. If a conversion is needed call into the 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // runtime to convert and clamp. 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(eax, Immediate(kSmiTagMask)); 868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &slow); 8696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ebx, ecx); 8706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ SmiUntag(ebx); 8716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(ebx, FieldOperand(edi, PixelArray::kLengthOffset)); 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &slow); 8736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ecx, eax); // Save the value. Key is not longer needed. 8746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ SmiUntag(ecx); 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { // Clamp the value to [0..255]. 8763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label done; 8776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(ecx, Immediate(0xFFFFFF00)); 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &done); 8796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ setcc(negative, ecx); // 1 if negative, 0 if positive. 8806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ dec_b(ecx); // 0 if negative, 255 if positive. 881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&done); 882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 8836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edi, FieldOperand(edi, PixelArray::kExternalPointerOffset)); 8846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov_b(Operand(edi, ebx, times_1, 0), ecx); 8856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret(0); // Return value in eax. 886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Extra capacity case: Check if there is extra capacity to 888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // perform the store and update the length. Used for adding one 889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // element to the array by writing to array[array.length]. 890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&extra); 891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: value 8926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver, a JSArray 8936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: key, a smi. 8946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edi: receiver->elements, a FixedArray 8956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // flags: compare (ecx, edx.length()) 896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &slow, not_taken); // do not leave holes in the array 8977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); 898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &slow, not_taken); 8996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Add 1 to receiver->length, and go to fast array write. 9006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ add(FieldOperand(edx, JSArray::kLengthOffset), 9017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Immediate(Smi::FromInt(1))); 902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&fast); 903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Array case: Get the length and the elements array from the JS 905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // array. Check that the array is in fast mode; if it is the 906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // length is always a smi. 907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&array); 908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: value 9096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver, a JSArray 9106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: key, a smi. 9116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 9126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true); 913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the key against the length in the array, compute the 915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // address to store into and fall through to fast case. 9166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. 917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &extra, not_taken); 918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fast case: Do the store. 920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fast); 921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: value 9226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: key (a smi) 9236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver 9246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edi: FixedArray receiver->elements 92525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ mov(CodeGenerator::FixedArrayElementOperand(edi, ecx), eax); 926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update write barrier for the elements array address. 927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(eax)); 9286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ RecordWrite(edi, 0, edx, ecx); 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm, 9343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ExternalArrayType array_type) { 9353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ----------- S t a t e ------------- 9363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // -- eax : value 9376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : key 9386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- edx : receiver 9393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // -- esp[0] : return address 9403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ----------------------------------- 9413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label slow, check_heap_number; 9423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the object isn't a smi. 9443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ test(edx, Immediate(kSmiTagMask)); 9453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(zero, &slow); 9463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Get the map from the receiver. 9476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); 9483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the receiver does not require access checks. We need 9493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // to do this because this generic stub does not perform map checks. 9507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test_b(FieldOperand(edi, Map::kBitFieldOffset), 9517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1 << Map::kIsAccessCheckNeeded); 9523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_zero, &slow); 9533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the key is a smi. 9546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(ecx, Immediate(kSmiTagMask)); 9553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_zero, &slow); 9563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Get the instance type from the map of the receiver. 9576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CmpInstanceType(edi, JS_OBJECT_TYPE); 9583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, &slow); 9593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the elements array is the appropriate type of 9613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ExternalArray. 9623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // eax: value 9636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver, a JSObject 9646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: key, a smi 9656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 9666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CheckMap(edi, Handle<Map>(Heap::MapForExternalArrayType(array_type)), 9676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block &slow, true); 9683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the index is in range. 9706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ebx, ecx); 9716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ SmiUntag(ebx); 9726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(ebx, FieldOperand(edi, ExternalArray::kLengthOffset)); 9733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Unsigned comparison catches both negative and too-large values. 9743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(above_equal, &slow); 9753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Handle both smis and HeapNumbers in the fast path. Go to the 9773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // runtime for all other kinds of values. 9783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // eax: value 9796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver 9806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: key 9816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edi: elements array 9823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ebx: untagged index 9833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ test(eax, Immediate(kSmiTagMask)); 9843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, &check_heap_number); 9853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // smi case 9866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ecx, eax); // Preserve the value in eax. Key is no longer needed. 9876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ SmiUntag(ecx); 9886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); 9893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ecx: base pointer of external storage 9903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block switch (array_type) { 9913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalByteArray: 9923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedByteArray: 9936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov_b(Operand(edi, ebx, times_1, 0), ecx); 9943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 9953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalShortArray: 9963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedShortArray: 9976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov_w(Operand(edi, ebx, times_2, 0), ecx); 9983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 9993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalIntArray: 10003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedIntArray: 10016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(Operand(edi, ebx, times_4, 0), ecx); 10023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 10033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalFloatArray: 10043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Need to perform int-to-float conversion. 10056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(ecx); 10063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fild_s(Operand(esp, 0)); 10076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(ecx); 10086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ fstp_s(Operand(edi, ebx, times_4, 0)); 10093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 10103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block default: 10113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block UNREACHABLE(); 10123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 10133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 10146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret(0); // Return the original value. 10153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&check_heap_number); 10176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // eax: value 10186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver 10196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: key 10206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edi: elements array 10216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ebx: untagged index 10223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 10233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Immediate(Factory::heap_number_map())); 10243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, &slow); 10253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // The WebGL specification leaves the behavior of storing NaN and 10273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // +/-Infinity into integer arrays basically undefined. For more 10283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // reproducible behavior, convert these to zero. 10293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); 10306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); 10313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ebx: untagged index 10326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edi: base pointer of external storage 10333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // top of FPU stack: value 10343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (array_type == kExternalFloatArray) { 10356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ fstp_s(Operand(edi, ebx, times_4, 0)); 10363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ret(0); 10373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 10383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Need to perform float-to-int conversion. 10393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Test the top of the FP stack for NaN. 10403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label is_nan; 10413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fucomi(0); 10423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(parity_even, &is_nan); 10433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (array_type != kExternalUnsignedIntArray) { 10456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(ecx); // Make room on stack 10463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fistp_s(Operand(esp, 0)); 10476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(ecx); 10483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 10493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // fistp stores values as signed integers. 10503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // To represent the entire range, we need to store as a 64-bit 10513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // int and discard the high 32 bits. 10526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ sub(Operand(esp), Immediate(2 * kPointerSize)); 10533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fistp_d(Operand(esp, 0)); 10546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(ecx); 10556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ add(Operand(esp), Immediate(kPointerSize)); 10563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 10576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: untagged integer value 10583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block switch (array_type) { 10593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalByteArray: 10603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedByteArray: 10616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov_b(Operand(edi, ebx, times_1, 0), ecx); 10623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 10633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalShortArray: 10643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedShortArray: 10656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov_w(Operand(edi, ebx, times_2, 0), ecx); 10663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 10673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalIntArray: 10683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedIntArray: { 10693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // We also need to explicitly check for +/-Infinity. These are 10703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // converted to MIN_INT, but we need to be careful not to 10713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // confuse with legal uses of MIN_INT. 10723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label not_infinity; 10733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // This test would apparently detect both NaN and Infinity, 10743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // but we've already checked for NaN using the FPU hardware 10753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // above. 10766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov_w(edx, FieldOperand(eax, HeapNumber::kValueOffset + 6)); 10776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ and_(edx, 0x7FF0); 10786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(edx, 0x7FF0); 10793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, ¬_infinity); 10806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ecx, 0); 10813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(¬_infinity); 10826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(Operand(edi, ebx, times_4, 0), ecx); 10833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 10843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 10853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block default: 10863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block UNREACHABLE(); 10873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 10883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 10896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret(0); // Return original value. 10903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&is_nan); 10923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ffree(); 10933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fincstp(); 10943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block switch (array_type) { 10953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalByteArray: 10963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedByteArray: 10976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov_b(Operand(edi, ebx, times_1, 0), 0); 10983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 10993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalShortArray: 11003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedShortArray: 11016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ xor_(ecx, Operand(ecx)); 11026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov_w(Operand(edi, ebx, times_2, 0), ecx); 11033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 11043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalIntArray: 11053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedIntArray: 11066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(Operand(edi, ebx, times_4, 0), Immediate(0)); 11073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 11083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block default: 11093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block UNREACHABLE(); 11103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 11113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 11126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret(0); // Return the original value. 11133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 11143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 11153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Slow case: call runtime. 11163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&slow); 1117402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateRuntimeSetProperty(masm); 11183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 11193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 11203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Defined in ic.cc. 1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* CallIC_Miss(Arguments args); 1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// The generated code does not accept smi keys. 11257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// The generated code falls through if both probes miss. 11267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void GenerateMonomorphicCacheProbe(MacroAssembler* masm, 11277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int argc, 11287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Code::Kind kind, 11297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label* miss) { 1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1131e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 11327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- edx : receiver 1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 11347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label number, non_number, non_string, boolean, probe; 1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the stub cache. 1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Flags flags = 11387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Code::ComputeFlags(kind, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc); 1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, eax); 1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the stub cache probing failed, the receiver might be a value. 1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // For value objects, we use the map of the prototype objects for 1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the corresponding JSValue for the cache and that is what we need 1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to probe. 1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for number. 1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(edx, Immediate(kSmiTagMask)); 1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &number, not_taken); 1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ebx); 1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &non_number, taken); 1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&number); 1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadGlobalFunctionPrototype( 1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm, Context::NUMBER_FUNCTION_INDEX, edx); 1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&probe); 1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for string. 1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&non_number); 11587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ CmpInstanceType(ebx, FIRST_NONSTRING_TYPE); 1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &non_string, taken); 1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadGlobalFunctionPrototype( 1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm, Context::STRING_FUNCTION_INDEX, edx); 1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&probe); 1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for boolean. 1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&non_string); 1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(edx, Factory::true_value()); 1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &boolean, not_taken); 1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(edx, Factory::false_value()); 11697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(not_equal, miss, taken); 1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&boolean); 1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadGlobalFunctionPrototype( 1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm, Context::BOOLEAN_FUNCTION_INDEX, edx); 1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the stub cache for the value object. 1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&probe); 1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg); 1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GenerateNormalHelper(MacroAssembler* masm, 1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int argc, 1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_global_object, 1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 1184e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------- S t a t e ------------- 1185e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 1186e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- edx : receiver 1187e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 1188e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1189e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 1190e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 1191e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------------------------------- 1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1193e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Search dictionary - put result in register edi. 1194e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(edi, edx); 11957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDictionaryLoad( 11967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch masm, miss, edx, ecx, eax, edi, ebx, edi, CHECK_DICTIONARY); 1197e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1198e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the result is not a smi. 1199e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ test(edi, Immediate(kSmiTagMask)); 1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, miss, not_taken); 1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1202e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the value is a JavaScript function, fetching its map into eax. 1203e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax); 1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, miss, not_taken); 1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1206e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Patch the receiver on stack with the global proxy if necessary. 1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (is_global_object) { 1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the function. 1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount actual(argc); 1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeFunction(edi, actual, JUMP_FUNCTION); 1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// The generated code never falls through. 12187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void GenerateCallNormal(MacroAssembler* masm, int argc, Label* miss) { 1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1220e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 1221e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 1222e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1223e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 1224e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 12267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label global_object, non_global_object; 1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver of the function from the stack; 1 ~ return address. 1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(edx, Immediate(kSmiTagMask)); 12337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(zero, miss, not_taken); 1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver is a valid JS object. 1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); 1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(eax, FieldOperand(ebx, Map::kInstanceTypeOffset)); 1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, FIRST_JS_OBJECT_TYPE); 12397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(below, miss, not_taken); 1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If this assert fails, we have to check upper bound too. 1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for access to global object. 1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, JS_GLOBAL_OBJECT_TYPE); 1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &global_object); 1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, JS_BUILTINS_OBJECT_TYPE); 1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &non_global_object); 1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Accessing global object: Load and invoke. 1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&global_object); 1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the global object does not require access checks. 12537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test_b(FieldOperand(ebx, Map::kBitFieldOffset), 12547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1 << Map::kIsAccessCheckNeeded); 12557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(not_equal, miss, not_taken); 12567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateNormalHelper(masm, argc, true, miss); 1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Accessing non-global object: Check for access to global proxy. 1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label global_proxy, invoke; 1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&non_global_object); 1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, JS_GLOBAL_PROXY_TYPE); 1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &global_proxy, not_taken); 1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the non-global, non-global-proxy object does not 1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // require access checks. 12657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test_b(FieldOperand(ebx, Map::kBitFieldOffset), 12667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1 << Map::kIsAccessCheckNeeded); 12677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(not_equal, miss, not_taken); 1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&invoke); 12697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateNormalHelper(masm, argc, false, miss); 1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Global object proxy access: Check access rights. 1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&global_proxy); 12737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ CheckAccessGlobalProxy(edx, eax, miss); 1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&invoke); 1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) { 1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1280e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 1281e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 1282e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1283e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 1284e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver of the function from the stack; 1 ~ return address. 1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Enter an internal frame. 1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ EnterInternalFrame(); 1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push the receiver and the name of the function. 1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(edx); 1295e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(ecx); 1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call the entry. 1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CEntryStub stub(1); 1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, Immediate(2)); 13007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(ebx, Immediate(ExternalReference(IC_Utility(id)))); 1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CallStub(&stub); 1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move result to edi and exit the internal frame. 1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edi, eax); 1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LeaveInternalFrame(); 1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the receiver is a global object of some sort. 1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label invoke, global; 1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); // receiver 1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(edx, Immediate(kSmiTagMask)); 1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &invoke, not_taken); 1312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); 1313e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 1314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(ebx, JS_GLOBAL_OBJECT_TYPE); 1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &global); 1316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(ebx, JS_BUILTINS_OBJECT_TYPE); 1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &invoke); 1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack. 1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&global); 1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the function. 1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount actual(argc); 1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&invoke); 1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeFunction(edi, actual, JUMP_FUNCTION); 1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { 13327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------- S t a t e ------------- 13337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ecx : name 13347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[0] : return address 13357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc - n) * 4] : arg[n] (zero-based) 13367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ... 13377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc + 1) * 4] : receiver 13387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------------------------------- 13397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label miss; 13417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Get the receiver of the function from the stack; 1 ~ return address. 13427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 13437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC, &miss); 13447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&miss); 13457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateMiss(masm, argc); 13467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 13477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid CallIC::GenerateNormal(MacroAssembler* masm, int argc) { 13507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label miss; 13517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateCallNormal(masm, argc, &miss); 13527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&miss); 13537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateMiss(masm, argc); 13547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 13557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid CallIC::GenerateMiss(MacroAssembler* masm, int argc) { 13587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateCallMiss(masm, argc, IC::kCallIC_Miss); 13597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 13607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { 13637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------- S t a t e ------------- 13647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ecx : name 13657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[0] : return address 13667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc - n) * 4] : arg[n] (zero-based) 13677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ... 13687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc + 1) * 4] : receiver 13697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------------------------------- 13707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Get the receiver of the function from the stack; 1 ~ return address. 13727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 13737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label do_call, slow_call, slow_load, slow_reload_receiver; 13757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label check_number_dictionary, check_string, lookup_monomorphic_cache; 13767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_smi, index_string; 13777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the key is a smi. 13797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test(ecx, Immediate(kSmiTagMask)); 13807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(not_zero, &check_string, not_taken); 13817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_smi); 13837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Now the key is known to be a smi. This place is also jumped to from 13847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // where a numeric string is converted to a smi. 13857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateKeyedLoadReceiverCheck(masm, edx, eax, &slow_call); 13877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateFastArrayLoad(masm, 13897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch edx, 13907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ecx, 13917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch eax, 13927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch edi, 13937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &check_number_dictionary, 13947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &slow_load); 13957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ IncrementCounter(&Counters::keyed_call_generic_smi_fast, 1); 13967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&do_call); 13987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // receiver in edx is not used after this point. 13997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ecx: key 14007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // edi: function 14017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the value in edi is a JavaScript function. 14037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test(edi, Immediate(kSmiTagMask)); 14047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(zero, &slow_call, not_taken); 14057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax); 14067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(not_equal, &slow_call, not_taken); 14077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Invoke the function. 14087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ParameterCount actual(argc); 14097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ InvokeFunction(edi, actual, JUMP_FUNCTION); 14107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&check_number_dictionary); 14127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // eax: elements 14137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ecx: smi key 14147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check whether the elements is a number dictionary. 14157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ CheckMap(eax, Factory::hash_table_map(), &slow_load, true); 14167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(ebx, ecx); 14177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ SmiUntag(ebx); 14187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ebx: untagged index 14197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Receiver in edx will be clobbered, need to reload it on miss. 14207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateNumberDictionaryLoad(masm, 14217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &slow_reload_receiver, 14227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch eax, 14237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ecx, 14247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ebx, 14257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch edx, 14267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch edi, 14277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch edi); 14287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ IncrementCounter(&Counters::keyed_call_generic_smi_dict, 1); 14297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&do_call); 14307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&slow_reload_receiver); 14327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 14337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&slow_load); 14357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // This branch is taken when calling KeyedCallIC_Miss is neither required 14367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // nor beneficial. 14377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ IncrementCounter(&Counters::keyed_call_generic_slow_load, 1); 14387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ EnterInternalFrame(); 14397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(ecx); // save the key 14407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(edx); // pass the receiver 14417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(ecx); // pass the key 14427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ CallRuntime(Runtime::kKeyedGetProperty, 2); 14437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(ecx); // restore the key 14447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LeaveInternalFrame(); 14457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(edi, eax); 14467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&do_call); 14477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&check_string); 14497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateKeyStringCheck(masm, ecx, eax, ebx, &index_string, &slow_call); 14507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // The key is known to be a symbol. 14527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // If the receiver is a regular JS object with slow properties then do 14537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // a quick inline probe of the receiver's dictionary. 14547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Otherwise do the monomorphic cache probe. 14557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateKeyedLoadReceiverCheck(masm, edx, eax, &lookup_monomorphic_cache); 14567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset)); 14587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 14597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Immediate(Factory::hash_table_map())); 14607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(not_equal, &lookup_monomorphic_cache, not_taken); 14617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDictionaryLoad(masm, 14637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &slow_load, 14647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch edx, 14657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ecx, 14667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ebx, 14677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch eax, 14687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch edi, 14697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch edi, 14707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch DICTIONARY_CHECK_DONE); 14717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ IncrementCounter(&Counters::keyed_call_generic_lookup_dict, 1); 14727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&do_call); 14737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&lookup_monomorphic_cache); 14757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ IncrementCounter(&Counters::keyed_call_generic_lookup_cache, 1); 14767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC, &slow_call); 14777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Fall through on miss. 14787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&slow_call); 14807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // This branch is taken if: 14817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // - the receiver requires boxing or access check, 14827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // - the key is neither smi nor symbol, 14837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // - the value loaded is not a function, 14847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // - there is hope that the runtime will create a monomorphic call stub 14857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // that will get fetched next time. 14867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ IncrementCounter(&Counters::keyed_call_generic_slow, 1); 14877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateMiss(masm, argc); 14887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_string); 14907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateIndexFromHash(masm, ecx, ebx, &index_smi); 14917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 14927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { 14957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label miss; 14967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateCallNormal(masm, argc, &miss); 14977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&miss); 14987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateMiss(masm, argc); 14997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 15007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 15017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 15027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) { 15037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss); 15047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 15057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 15067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Defined in ic.cc. 1508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* LoadIC_Miss(Arguments args); 1509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateMegamorphic(MacroAssembler* masm) { 1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1512402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the stub cache. 1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, 1519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NOT_IN_LOOP, 1520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MONOMORPHIC); 1521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCache::GenerateProbe(masm, flags, eax, ecx, ebx, edx); 1522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cache miss: Jump to runtime. 1524402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateMiss(masm); 1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateNormal(MacroAssembler* masm) { 1529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1530402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 1531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 1532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss, probe, global; 1535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 1537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(eax, Immediate(kSmiTagMask)); 1538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &miss, not_taken); 1539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver is a valid JS object. 1541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 1542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(edx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 1543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(edx, FIRST_JS_OBJECT_TYPE); 1544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(less, &miss, not_taken); 1545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If this assert fails, we have to check upper bound too. 1547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 1548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for access to global object (unlikely). 1550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(edx, JS_GLOBAL_PROXY_TYPE); 1551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &global, not_taken); 1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for non-global object that requires access check. 15547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test_b(FieldOperand(ebx, Map::kBitFieldOffset), 15557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1 << Map::kIsAccessCheckNeeded); 1556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &miss, not_taken); 1557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Search the dictionary placing the result in eax. 1559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&probe); 1560402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateDictionaryLoad(masm, 1561402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu &miss, 1562402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu eax, 1563402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ecx, 1564402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu edx, 1565402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu edi, 1566402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ebx, 15677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch edi, 1568402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu CHECK_DICTIONARY); 1569402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, edi); 1570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 1571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Global object access: Check access rights. 1573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&global); 1574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CheckAccessGlobalProxy(eax, edx, &miss); 1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&probe); 1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Cache miss: Jump to runtime. 1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 1579402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateMiss(masm); 1580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateMiss(MacroAssembler* masm) { 1584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1585402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 1586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 1587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); 1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(eax); // receiver 1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); // name 1593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); // return address 1594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform tail call to the entry. 15966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss)); 15976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(ref, 2, 1); 1598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// One byte opcode for test eax,0xXXXXXXXX. 1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const byte kTestEaxByte = 0xA9; 1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::ClearInlinedVersion(Address address) { 1606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reset the map check of the inlined inobject property load (if 1607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // present) to guarantee failure by holding an invalid map (the null 1608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // value). The offset can be patched to anything. 1609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PatchInlinedLoad(address, Heap::null_value(), kMaxInt); 1610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid KeyedLoadIC::ClearInlinedVersion(Address address) { 1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Insert null as the map to check for to make sure the map check fails 1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sending control flow to the IC instead of the inlined version. 1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PatchInlinedLoad(address, Heap::null_value()); 1617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid KeyedStoreIC::ClearInlinedVersion(Address address) { 1621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Insert null as the elements map to check for. This will make 1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sure that the elements fast-case map check fails so that control 1623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // flows to the IC instead of the inlined version. 1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PatchInlinedStore(address, Heap::null_value()); 1625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid KeyedStoreIC::RestoreInlinedVersion(Address address) { 1629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore the fast-case elements map check so that the inlined 1630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // version can be used again. 1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PatchInlinedStore(address, Heap::fixed_array_map()); 1632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { 1636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The address of the instruction following the call. 1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address test_instruction_address = 1638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block address + Assembler::kCallTargetAddressOffset; 1639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the instruction following the call is not a test eax, nothing 1640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // was inlined. 1641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*test_instruction_address != kTestEaxByte) return false; 1642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address delta_address = test_instruction_address + 1; 1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The delta to the start of the map check instruction. 1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int delta = *reinterpret_cast<int*>(delta_address); 1646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The map address is the last 4 bytes of the 7-byte 1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // operand-immediate compare instruction, so we add 3 to get the 1649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // offset to the last 4 bytes. 1650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address map_address = test_instruction_address + delta + 3; 1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *(reinterpret_cast<Object**>(map_address)) = map; 1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The offset is in the last 4 bytes of a six byte 1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // memory-to-register move instruction, so we add 2 to get the 1655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // offset to the last 4 bytes. 1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address offset_address = 1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block test_instruction_address + delta + kOffsetToLoadInstruction + 2; 1658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; 1659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool PatchInlinedMapCheck(Address address, Object* map) { 1664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address test_instruction_address = 1665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block address + Assembler::kCallTargetAddressOffset; 1666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The keyed load has a fast inlined case if the IC call instruction 1667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is immediately followed by a test instruction. 1668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*test_instruction_address != kTestEaxByte) return false; 1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fetch the offset from the test instruction to the map cmp 1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // instruction. This offset is stored in the last 4 bytes of the 5 1672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // byte test instruction. 1673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address delta_address = test_instruction_address + 1; 1674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int delta = *reinterpret_cast<int*>(delta_address); 1675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the map address. The map address is in the last 4 bytes 1676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // of the 7-byte operand-immediate compare instruction, so we add 3 1677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to the offset to get the map address. 1678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address map_address = test_instruction_address + delta + 3; 1679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the map check. 1680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *(reinterpret_cast<Object**>(map_address)) = map; 1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 1682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool KeyedLoadIC::PatchInlinedLoad(Address address, Object* map) { 1686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return PatchInlinedMapCheck(address, map); 1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool KeyedStoreIC::PatchInlinedStore(Address address, Object* map) { 1691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return PatchInlinedMapCheck(address, map); 1692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Defined in ic.cc. 1696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadIC_Miss(Arguments args); 1697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { 1700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1701402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 1702402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 1703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1706402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(ebx); 1707402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(edx); // receiver 1708402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(eax); // name 1709402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(ebx); // return address 1710402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1711402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Perform tail call to the entry. 17126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss)); 17136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(ref, 2, 1); 1714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1717402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { 1718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1719402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 1720402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 1721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); 1725402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(edx); // receiver 1726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(eax); // name 1727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); // return address 1728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform tail call to the entry. 17306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 1731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StoreIC::GenerateMegamorphic(MacroAssembler* masm) { 1735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 1737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 17384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- edx : receiver 1739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, 1743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NOT_IN_LOOP, 1744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MONOMORPHIC); 1745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg); 1746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cache miss: Jump to runtime. 17484515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke GenerateMiss(masm); 1749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 17524515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid StoreIC::GenerateMiss(MacroAssembler* masm) { 1753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 1755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 17564515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- edx : receiver 1757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); 17614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(edx); 1762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); 1763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(eax); 1764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); 1765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform tail call to the entry. 17676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_Miss)); 17686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(ref, 3, 1); 17696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 17706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17726ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid StoreIC::GenerateArrayLength(MacroAssembler* masm) { 17736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 17746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- eax : value 17756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : name 17766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- edx : receiver 17776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[0] : return address 17786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 17796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 17806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // This accepts as a receiver anything JSObject::SetElementsLength accepts 17816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // (currently anything except for external and pixel arrays which means 17826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // anything with elements of FixedArray type.), but currently is restricted 17836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // to JSArray. 17846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Value must be a number, but only smis are accepted as the most common case. 17856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss; 17876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register receiver = edx; 17896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register value = eax; 17906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch = ebx; 17916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the receiver isn't a smi. 17936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(receiver, Immediate(kSmiTagMask)); 17946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(zero, &miss, not_taken); 17956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the object is a JS array. 17976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); 17986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_equal, &miss, not_taken); 17996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that elements are FixedArray. 18016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(scratch, FieldOperand(receiver, JSArray::kElementsOffset)); 18026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch); 18036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_equal, &miss, not_taken); 18046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that value is a smi. 18066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(value, Immediate(kSmiTagMask)); 18076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_zero, &miss, not_taken); 18086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Prepare tail call to StoreIC_ArrayLength. 18106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(scratch); 18116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(receiver); 18126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(value); 18136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(scratch); // return address 18146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_ArrayLength)); 18166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(ref, 2, 1); 18176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss); 18196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GenerateMiss(masm); 1821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Defined in ic.cc. 1825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedStoreIC_Miss(Arguments args); 1826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1827402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) { 1828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 18306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : key 18316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- edx : receiver 1832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 18356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(ebx); 18366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(edx); 1837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); 18386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(eax); 18396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(ebx); 1840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to runtime routine. 18426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallRuntime(Runtime::kSetProperty, 3, 1); 1843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1846402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { 1847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 18496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : key 18506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- edx : receiver 1851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 18546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(ebx); 18556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(edx); 1856402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(ecx); 18576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(eax); 18586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(ebx); 1859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to runtime routine. 18616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); 18626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(ref, 3, 1); 1863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 1866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 1869f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1870f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_IA32 1871