ic-ia32.cc revision 25f6136652d8341ed047e7fc1a450af5bd218ea9
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2006-2008 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 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "codegen-inl.h" 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "ic-inl.h" 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "runtime.h" 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "stub-cache.h" 34d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "utils.h" 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ---------------------------------------------------------------------------- 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Static IC stub generators. 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm) 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper function used to load a property from a dictionary backing storage. 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This function may return false negatives, so miss_label 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// must always call a backup property load that is complete. 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This function is safe to call if the receiver has fast properties, 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// or if name is not a symbol, and will jump to the miss_label in that case. 51e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkestatic void GenerateDictionaryLoad(MacroAssembler* masm, 52e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* miss_label, 53402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register receiver, 54402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register name, 55e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register r0, 56e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register r1, 57e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register r2, 58e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DictionaryCheck check_dictionary) { 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Register use: 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 61402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // name - holds the name of the property and is unchanged. 62402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // receiver - holds the receiver and is unchanged. 63402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Scratch registers: 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0 - used to hold the property dictionary. 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 66402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // r1 - used for the index into the property dictionary 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // - holds the result on exit. 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2 - used to hold the capacity of the property dictionary. 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label done; 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for the absence of an interceptor. 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the map into r0. 75402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(r0, FieldOperand(receiver, JSObject::kMapOffset)); 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Bail out if the receiver has a named interceptor. 786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(FieldOperand(r0, Map::kBitFieldOffset), 796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Immediate(1 << Map::kHasNamedInterceptor)); 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, miss_label, not_taken); 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Bail out if we have a JS global proxy object. 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(r0, FieldOperand(r0, Map::kInstanceTypeOffset)); 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, JS_GLOBAL_PROXY_TYPE); 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, miss_label, not_taken); 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Possible work-around for http://crbug.com/16276. 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, JS_GLOBAL_OBJECT_TYPE); 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, miss_label, not_taken); 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, JS_BUILTINS_OBJECT_TYPE); 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, miss_label, not_taken); 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 93e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Load properties array. 94402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(r0, FieldOperand(receiver, JSObject::kPropertiesOffset)); 95e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 96e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the properties array is a dictionary. 97e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (check_dictionary == CHECK_DICTIONARY) { 98e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(FieldOperand(r0, HeapObject::kMapOffset), 99e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Immediate(Factory::hash_table_map())); 100e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_equal, miss_label); 101e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the capacity mask. 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kCapacityOffset = 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StringDictionary::kHeaderSize + 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StringDictionary::kCapacityIndex * kPointerSize; 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, FieldOperand(r0, kCapacityOffset)); 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ shr(r2, kSmiTagSize); // convert smi to int 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ dec(r2); 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Generate an unrolled loop that performs a few probes before 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // giving up. Measurements done on Gmail indicate that 2 probes 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // cover ~93% of loads from dictionaries. 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kProbes = 4; 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kElementsStartOffset = 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StringDictionary::kHeaderSize + 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StringDictionary::kElementsStartIndex * kPointerSize; 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < kProbes; i++) { 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the masked index: (hash + i + i * i) & mask. 120d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r1, FieldOperand(name, String::kHashFieldOffset)); 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ shr(r1, String::kHashShift); 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (i > 0) { 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(Operand(r1), Immediate(StringDictionary::GetProbeOffset(i))); 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(r1, Operand(r2)); 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Scale the index by multiplying by the entry size. 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(StringDictionary::kEntrySize == 3); 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(r1, Operand(r1, r1, times_2, 0)); // r1 = r1 * 3 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the key is identical to the name. 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(name, 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand(r0, r1, times_4, kElementsStartOffset - kHeapObjectTag)); 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (i != kProbes - 1) { 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &done, taken); 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, miss_label, not_taken); 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the value is a normal property. 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&done); 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(Operand(r0, r1, times_4, kDetailsOffset - kHeapObjectTag), 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, miss_label, not_taken); 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the value at the masked, scaled index. 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kValueOffset = kElementsStartOffset + kPointerSize; 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r1, Operand(r0, r1, times_4, kValueOffset - kHeapObjectTag)); 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1546ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void GenerateNumberDictionaryLoad(MacroAssembler* masm, 1556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* miss, 1566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register elements, 1576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register key, 1586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register r0, 1596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register r1, 1606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register r2) { 1616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Register use: 1626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 1636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // elements - holds the slow-case elements of the receiver and is unchanged. 1646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 1656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // key - holds the smi key on entry and is unchanged if a branch is 1666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // performed to the miss label. If the load succeeds and we 1676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // fall through, key holds the result on exit. 1686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 1696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Scratch registers: 1706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 1716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // r0 - holds the untagged key on entry and holds the hash once computed. 1726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 1736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // r1 - used to hold the capacity mask of the dictionary 1746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 1756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // r2 - used for the index into the dictionary. 1766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label done; 1776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Compute the hash code from the untagged key. This must be kept in sync 1796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // with ComputeIntegerHash in utils.h. 1806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 1816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // hash = ~hash + (hash << 15); 1826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r1, r0); 1836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ not_(r0); 1846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ shl(r1, 15); 1856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ add(r0, Operand(r1)); 1866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // hash = hash ^ (hash >> 12); 1876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r1, r0); 1886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ shr(r1, 12); 1896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ xor_(r0, Operand(r1)); 1906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // hash = hash + (hash << 2); 1916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ lea(r0, Operand(r0, r0, times_4, 0)); 1926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // hash = hash ^ (hash >> 4); 1936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r1, r0); 1946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ shr(r1, 4); 1956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ xor_(r0, Operand(r1)); 1966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // hash = hash * 2057; 1976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ imul(r0, r0, 2057); 1986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // hash = hash ^ (hash >> 16); 1996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r1, r0); 2006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ shr(r1, 16); 2016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ xor_(r0, Operand(r1)); 2026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Compute capacity mask. 2046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r1, FieldOperand(elements, NumberDictionary::kCapacityOffset)); 2056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ shr(r1, kSmiTagSize); // convert smi to int 2066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ dec(r1); 2076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Generate an unrolled loop that performs a few probes before giving up. 2096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kProbes = 4; 2106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (int i = 0; i < kProbes; i++) { 2116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Use r2 for index calculations and keep the hash intact in r0. 2126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r2, r0); 2136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Compute the masked index: (hash + i + i * i) & mask. 2146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (i > 0) { 2156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ add(Operand(r2), Immediate(NumberDictionary::GetProbeOffset(i))); 2166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ and_(r2, Operand(r1)); 2186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Scale the index by multiplying by the entry size. 2206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(NumberDictionary::kEntrySize == 3); 2216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 2226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check if the key matches. 2246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(key, FieldOperand(elements, 2256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block r2, 2266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block times_pointer_size, 2276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NumberDictionary::kElementsStartOffset)); 2286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (i != (kProbes - 1)) { 2296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(equal, &done, taken); 2306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 2316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_equal, miss, not_taken); 2326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&done); 2366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the value is a normal propety. 2376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kDetailsOffset = 2386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NumberDictionary::kElementsStartOffset + 2 * kPointerSize; 2396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT_EQ(NORMAL, 0); 2406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), 2416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); 2426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_zero, miss); 2436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the value at the masked, scaled index. 2456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kValueOffset = 2466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NumberDictionary::kElementsStartOffset + kPointerSize; 2476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(key, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); 2486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 2496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The offset from the inlined patch site to the start of the 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// inlined load instruction. It is 7 bytes (test eax, imm) plus 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6 bytes (jne slow_label). 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int LoadIC::kOffsetToLoadInstruction = 13; 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateArrayLength(MacroAssembler* masm) { 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 259402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadArrayLength(masm, eax, edx, &miss); 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateStringLength(MacroAssembler* masm) { 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 273402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 279402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu StubCompiler::GenerateLoadStringLength(masm, eax, edx, ebx, &miss); 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) { 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 287402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadFunctionPrototype(masm, eax, edx, ebx, &miss); 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 301402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 302402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label slow, check_string, index_int, index_string; 306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label check_pixel_array, probe_dictionary; 3076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label check_number_dictionary; 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object isn't a smi. 310402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ test(edx, Immediate(kSmiTagMask)); 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &slow, not_taken); 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the map of the receiver. 314402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 315d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 316d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Check bit field. 317402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset)); 318d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ test(ebx, Immediate(kSlowCaseBitFieldMask)); 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &slow, not_taken); 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is some kind of JS object EXCEPT JS Value type. 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // In the case that the object is a value-wrapper object, 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // we enter the runtime system to make sure that indexing 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // into string objects work as intended. 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); 325402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CmpInstanceType(ecx, JS_OBJECT_TYPE); 326402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ j(below, &slow, not_taken); 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the key is a smi. 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(eax, Immediate(kSmiTagMask)); 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &check_string, not_taken); 330402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ebx, eax); 331402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ SmiUntag(ebx); 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the elements array of the object. 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&index_int); 334402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is in fast mode (not dictionary). 336402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CheckMap(ecx, Factory::fixed_array_map(), &check_pixel_array, true); 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the key (index) is within bounds. 338402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(ebx, FieldOperand(ecx, FixedArray::kLengthOffset)); 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &slow); 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fast case: Do the load. 341402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, FieldOperand(ecx, ebx, times_4, FixedArray::kHeaderSize)); 342402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(Operand(ecx), Immediate(Factory::the_hole_value())); 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // In case the loaded value is the_hole we have to consult GetProperty 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to ensure the prototype chain is searched. 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &slow); 346402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, ecx); 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&check_pixel_array); 351402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Check whether the elements is a pixel array. 352402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // edx: receiver 353402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ebx: untagged index 354402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // eax: key 355402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ecx: elements 3566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CheckMap(ecx, Factory::pixel_array_map(), &check_number_dictionary, true); 357402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(ebx, FieldOperand(ecx, PixelArray::kLengthOffset)); 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &slow); 359402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, FieldOperand(ecx, PixelArray::kExternalPointerOffset)); 360402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(eax, Operand(eax, ebx, times_1, 0)); 361402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ SmiTag(eax); 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&check_number_dictionary); 3656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check whether the elements is a number dictionary. 3666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver 3676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ebx: untagged index 3686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // eax: key 3696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: elements 3706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CheckMap(ecx, Factory::hash_table_map(), &slow, true); 3716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label slow_pop_receiver; 3726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Push receiver on the stack to free up a register for the dictionary 3736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // probing. 3746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(edx); 3756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GenerateNumberDictionaryLoad(masm, 3766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block &slow_pop_receiver, 3776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ecx, 3786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block eax, 3796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ebx, 3806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block edx, 3816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block edi); 3826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Pop receiver before returning. 3836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(edx); 3846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret(0); 3856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&slow_pop_receiver); 3876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Pop the receiver from the stack and jump to runtime. 3886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(edx); 3896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&slow); 391402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Slow case: jump to runtime. 392402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // edx: receiver 393402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // eax: key 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); 395402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateRuntimeGetProperty(masm); 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&check_string); 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The key is not a smi. 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Is it a string? 400402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // edx: receiver 401402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // eax: key 402402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ecx); 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &slow); 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Is the string an array index, with cached numeric value? 405d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(ebx, FieldOperand(eax, String::kHashFieldOffset)); 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(ebx, Immediate(String::kIsArrayIndexMask)); 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &index_string, not_taken); 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 409e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Is the string a symbol? 410402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(ebx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 411e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(kSymbolTag != 0); 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(ebx, Immediate(kIsSymbolMask)); 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &slow, not_taken); 414e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 415e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // If the receiver is a fast-case object, check the keyed lookup 416402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // cache. Otherwise probe the dictionary. 417402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset)); 418e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 419e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Immediate(Factory::hash_table_map())); 420e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, &probe_dictionary); 421e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 422e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Load the map of the receiver, compute the keyed lookup cache hash 423e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // based on 32 bits of the map pointer and the string hash. 424402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); 425402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, ebx); 426402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ shr(ecx, KeyedLookupCache::kMapHashShift); 427402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(edi, FieldOperand(eax, String::kHashFieldOffset)); 428402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ shr(edi, String::kHashShift); 429402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ xor_(ecx, Operand(edi)); 430402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ and_(ecx, KeyedLookupCache::kCapacityMask); 431e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 432e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Load the key (consisting of map and symbol) from the cache and 433e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // check for match. 434e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ExternalReference cache_keys 435e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke = ExternalReference::keyed_lookup_cache_keys(); 436402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(edi, ecx); 437e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ shl(edi, kPointerSizeLog2 + 1); 438e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys)); 439e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_equal, &slow); 440e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ add(Operand(edi), Immediate(kPointerSize)); 441402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(eax, Operand::StaticArray(edi, times_1, cache_keys)); 442e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_equal, &slow); 443e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 444e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Get field offset and check that it is an in-object property. 445402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // edx : receiver 446402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ebx : receiver's map 447402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // eax : key 448402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ecx : lookup cache index 449e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ExternalReference cache_field_offsets 450e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke = ExternalReference::keyed_lookup_cache_field_offsets(); 451402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(edi, 452402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Operand::StaticArray(ecx, times_pointer_size, cache_field_offsets)); 453402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(ecx, FieldOperand(ebx, Map::kInObjectPropertiesOffset)); 454402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(edi, Operand(ecx)); 455e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(above_equal, &slow); 456e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 457e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Load in-object property. 458402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ sub(edi, Operand(ecx)); 459402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset)); 460402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ add(ecx, Operand(edi)); 461402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, FieldOperand(edx, ecx, times_pointer_size, 0)); 462e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ret(0); 463e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 464e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Do a quick inline probe of the receiver's dictionary, if it 465e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // exists. 466e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&probe_dictionary); 467e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke GenerateDictionaryLoad(masm, 468e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke &slow, 469e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke edx, 470e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke eax, 471402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ebx, 472402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ecx, 473402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu edi, 474e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DICTIONARY_CHECK_DONE); 4756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(eax, ecx); 476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); 477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 478e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 479d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the hash field contains an array index pick it out. The assert checks 480d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // that the constants for the maximum number of digits for an array index 481d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // cached in the hash field and the number of bits reserved for it does not 482d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // conflict. 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < 484d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block (1 << String::kArrayIndexValueBits)); 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&index_string); 486402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ and_(ebx, String::kArrayIndexHashMask); 487402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ shr(ebx, String::kHashShift); 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&index_int); 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 492e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid KeyedLoadIC::GenerateString(MacroAssembler* masm) { 493e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------- S t a t e ------------- 4946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- eax : key (index) 495402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 496e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 497e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------------------------------- 4986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss; 4996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label index_not_smi; 5006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label index_out_of_range; 5016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label slow_char_code; 5026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label got_char_code; 5036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register receiver = edx; 5056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register index = eax; 5066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register code = ebx; 5076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch = ecx; 5086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block StringHelper::GenerateFastCharCodeAt(masm, 5106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block receiver, 5116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block index, 5126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block scratch, 5136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block code, 5146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block &miss, // When not a string. 5156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block &index_not_smi, 5166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block &index_out_of_range, 5176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block &slow_char_code); 5186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // If we didn't bail out, code register contains smi tagged char 5196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // code. 5206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&got_char_code); 5216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block StringHelper::GenerateCharFromCode(masm, code, eax, JUMP_FUNCTION); 5226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef DEBUG 5236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Abort("Unexpected fall-through from char from code tail call"); 5246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif 5256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check if key is a heap number. 5276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&index_not_smi); 5286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CheckMap(index, Factory::heap_number_map(), &miss, true); 5296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Push receiver and key on the stack (now that we know they are a 5316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // string and a number), and call runtime. 5326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&slow_char_code); 5336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ EnterInternalFrame(); 5346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(receiver); 5356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(index); 5366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CallRuntime(Runtime::kStringCharCodeAt, 2); 5376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(!code.is(eax)); 5386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(code, eax); 5396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ LeaveInternalFrame(); 540e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 5416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check if the runtime call returned NaN char code. If yes, return 5426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // undefined. Otherwise, we can continue. 5436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (FLAG_debug_code) { 5446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(kSmiTag == 0); 5456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(code, Immediate(kSmiTagMask)); 5466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(zero, &got_char_code); 5476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(scratch, FieldOperand(code, HeapObject::kMapOffset)); 5486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(scratch, Factory::heap_number_map()); 5496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Assert(equal, "StringCharCodeAt must return smi or heap number"); 5506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 5516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(code, Factory::nan_value()); 5526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_equal, &got_char_code); 5536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&index_out_of_range); 5546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Set(eax, Immediate(Factory::undefined_value())); 5556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret(0); 556e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 557e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&miss); 558e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke GenerateMiss(masm); 559e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 560e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 561e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 5623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm, 5633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ExternalArrayType array_type) { 5643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ----------- S t a t e ------------- 565402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 566402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 5673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // -- esp[0] : return address 5683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ----------------------------------- 5693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label slow, failed_allocation; 5703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 5713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the object isn't a smi. 572402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ test(edx, Immediate(kSmiTagMask)); 5733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(zero, &slow, not_taken); 5743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 5753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the key is a smi. 5763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ test(eax, Immediate(kSmiTagMask)); 5773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_zero, &slow, not_taken); 5783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 5793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Get the map of the receiver. 580402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 5813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the receiver does not require access checks. We need 5823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // to check this explicitly since this generic stub does not perform 5833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // map checks. 584402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset)); 5853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); 5863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_zero, &slow, not_taken); 5873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 588402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CmpInstanceType(ecx, JS_OBJECT_TYPE); 5893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, &slow, not_taken); 5903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 5913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the elements array is the appropriate type of 5923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ExternalArray. 593402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); 5943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Handle<Map> map(Heap::MapForExternalArrayType(array_type)); 595402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 5963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Immediate(map)); 5973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, &slow, not_taken); 5983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 599402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // eax: key, known to be a smi. 600402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // edx: receiver, known to be a JSObject. 601402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ebx: elements object, known to be an external array. 6023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the index is in range. 603402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, eax); 604402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ SmiUntag(ecx); // Untag the index. 605402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset)); 6063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Unsigned comparison catches both negative and too-large values. 6073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(above_equal, &slow); 6083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 609402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset)); 610402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ebx: base pointer of external storage 6113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block switch (array_type) { 6123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalByteArray: 613402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movsx_b(ecx, Operand(ebx, ecx, times_1, 0)); 6143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 6153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedByteArray: 616402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(ecx, Operand(ebx, ecx, times_1, 0)); 6173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 6183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalShortArray: 619402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movsx_w(ecx, Operand(ebx, ecx, times_2, 0)); 6203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 6213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedShortArray: 622402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_w(ecx, Operand(ebx, ecx, times_2, 0)); 6233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 6243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalIntArray: 6253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedIntArray: 626402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, Operand(ebx, ecx, times_4, 0)); 6273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 6283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalFloatArray: 629402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ fld_s(Operand(ebx, ecx, times_4, 0)); 6303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 6313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block default: 6323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block UNREACHABLE(); 6333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 6343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 6353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 6363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // For integer array types: 637402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ecx: value 6383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // For floating-point array type: 6393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // FP(0): value 6403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 6413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (array_type == kExternalIntArray || 6423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block array_type == kExternalUnsignedIntArray) { 6433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // For the Int and UnsignedInt array types, we need to see whether 6443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // the value can be represented in a Smi. If not, we need to convert 6453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // it to a HeapNumber. 6463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label box_int; 6473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (array_type == kExternalIntArray) { 648402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(ecx, 0xC0000000); 649402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ j(sign, &box_int); 6503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 6513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT_EQ(array_type, kExternalUnsignedIntArray); 6523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // The test is different for unsigned int values. Since we need 653402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // the value to be in the range of a positive smi, we can't 6543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // handle either of the top two bits being set in the value. 655402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ test(ecx, Immediate(0xC0000000)); 6563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_zero, &box_int); 6573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 6583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 659402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, ecx); 660402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ SmiTag(eax); 6613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ret(0); 6623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 6633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&box_int); 6643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 6653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Allocate a HeapNumber for the int and perform int-to-double 6663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // conversion. 6673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (array_type == kExternalIntArray) { 668402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(ecx); 6693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fild_s(Operand(esp, 0)); 670402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(ecx); 6713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 6723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(array_type == kExternalUnsignedIntArray); 6733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Need to zero-extend the value. 6743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // There's no fild variant for unsigned values, so zero-extend 6753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // to a 64-bit int manually. 6763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(Immediate(0)); 677402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(ecx); 6783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fild_d(Operand(esp, 0)); 679402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(ecx); 680402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(ecx); 6813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 6823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // FP(0): value 683402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); 6843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Set the value. 685402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, ecx); 6863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 6873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ret(0); 6883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (array_type == kExternalFloatArray) { 6893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // For the floating-point array type, we need to always allocate a 6903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // HeapNumber. 691402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); 6923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Set the value. 693402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, ecx); 6943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 6953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ret(0); 6963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 697402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, ecx); 698402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ SmiTag(eax); 6993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ret(0); 7003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 7013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If we fail allocation of the HeapNumber, we still have a value on 7033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // top of the FPU stack. Remove it. 7043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&failed_allocation); 7053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ffree(); 7063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fincstp(); 7073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Fall through to slow case. 7083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 709402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Slow case: Load key and receiver from stack and jump to runtime. 7103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&slow); 7113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1); 712402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateRuntimeGetProperty(masm); 713402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 714402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 715402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 716402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { 717402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------- S t a t e ------------- 718402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 719402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 720402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- esp[0] : return address 721402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------------------------------- 722402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label slow; 723402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 724402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Check that the receiver isn't a smi. 725402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ test(edx, Immediate(kSmiTagMask)); 726402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ j(zero, &slow, not_taken); 727402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 728402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Check that the key is a smi. 729402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ test(eax, Immediate(kSmiTagMask)); 730402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ j(not_zero, &slow, not_taken); 731402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 732402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Get the map of the receiver. 733402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 734402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 735402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Check that it has indexed interceptor and access checks 736402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // are not enabled for this object. 737402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(ecx, FieldOperand(ecx, Map::kBitFieldOffset)); 738402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ and_(Operand(ecx), Immediate(kSlowCaseBitFieldMask)); 739402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(Operand(ecx), Immediate(1 << Map::kHasIndexedInterceptor)); 740402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ j(not_zero, &slow, not_taken); 741402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 742402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Everything is fine, call runtime. 743402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(ecx); 744402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(edx); // receiver 745402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(eax); // key 746402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(ecx); // return address 747402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 748402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Perform tail call to the entry. 7496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference ref = ExternalReference( 7506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block IC_Utility(kKeyedLoadPropertyWithInterceptor)); 7516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(ref, 2, 1); 752402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 753402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ bind(&slow); 754402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateMiss(masm); 7553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 7563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { 759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 7616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : key 7626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- edx : receiver 763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label slow, fast, array, extra, check_pixel_array; 766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object isn't a smi. 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(edx, Immediate(kSmiTagMask)); 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &slow, not_taken); 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the map from the receiver. 7716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver does not require access checks. We need 773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to do this because this generic stub does not perform map checks. 7746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ movzx_b(ebx, FieldOperand(edi, Map::kBitFieldOffset)); 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &slow, not_taken); 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the key is a smi. 7786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(ecx, Immediate(kSmiTagMask)); 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &slow, not_taken); 7806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CmpInstanceType(edi, JS_ARRAY_TYPE); 781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &array); 782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is some kind of JS object. 7836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE); 7846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(below, &slow, not_taken); 785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Object case: Check key against length in the elements array. 787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: value 788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edx: JSObject 7896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: key (a smi) 7906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is in fast mode (not dictionary). 7926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true); 7936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ebx, Operand(ecx)); 7946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ SmiUntag(ebx); 7956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(ebx, FieldOperand(edi, Array::kLengthOffset)); 796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(below, &fast, taken); 797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Slow case: call runtime. 799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&slow); 800402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateRuntimeSetProperty(masm); 801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check whether the elements is a pixel array. 803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&check_pixel_array); 8046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // eax: value 8056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: key 8066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver 8076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edi: elements array 8086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CheckMap(edi, Factory::pixel_array_map(), &slow, true); 809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the value is a smi. If a conversion is needed call into the 810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // runtime to convert and clamp. 811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(eax, Immediate(kSmiTagMask)); 812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &slow); 8136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ebx, ecx); 8146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ SmiUntag(ebx); 8156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(ebx, FieldOperand(edi, PixelArray::kLengthOffset)); 816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &slow); 8176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ecx, eax); // Save the value. Key is not longer needed. 8186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ SmiUntag(ecx); 819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { // Clamp the value to [0..255]. 8203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label done; 8216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(ecx, Immediate(0xFFFFFF00)); 822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &done); 8236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ setcc(negative, ecx); // 1 if negative, 0 if positive. 8246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ dec_b(ecx); // 0 if negative, 255 if positive. 825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&done); 826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 8276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edi, FieldOperand(edi, PixelArray::kExternalPointerOffset)); 8286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov_b(Operand(edi, ebx, times_1, 0), ecx); 8296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret(0); // Return value in eax. 830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Extra capacity case: Check if there is extra capacity to 832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // perform the store and update the length. Used for adding one 833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // element to the array by writing to array[array.length]. 834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&extra); 835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: value 8366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver, a JSArray 8376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: key, a smi. 8386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edi: receiver->elements, a FixedArray 8396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // flags: compare (ecx, edx.length()) 840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &slow, not_taken); // do not leave holes in the array 8416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ebx, ecx); 8426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ SmiUntag(ebx); // untag 8436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(ebx, FieldOperand(edi, Array::kLengthOffset)); 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &slow, not_taken); 8456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Add 1 to receiver->length, and go to fast array write. 8466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ add(FieldOperand(edx, JSArray::kLengthOffset), 8476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Immediate(1 << kSmiTagSize)); 848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&fast); 849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Array case: Get the length and the elements array from the JS 851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // array. Check that the array is in fast mode; if it is the 852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // length is always a smi. 853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&array); 854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: value 8556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver, a JSArray 8566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: key, a smi. 8576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 8586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true); 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the key against the length in the array, compute the 861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // address to store into and fall through to fast case. 8626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &extra, not_taken); 864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fast case: Do the store. 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fast); 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: value 8686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: key (a smi) 8696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver 8706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edi: FixedArray receiver->elements 87125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ mov(CodeGenerator::FixedArrayElementOperand(edi, ecx), eax); 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update write barrier for the elements array address. 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(eax)); 8746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ RecordWrite(edi, 0, edx, ecx); 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm, 8803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ExternalArrayType array_type) { 8813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ----------- S t a t e ------------- 8823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // -- eax : value 8836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : key 8846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- edx : receiver 8853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // -- esp[0] : return address 8863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ----------------------------------- 8873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label slow, check_heap_number; 8883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the object isn't a smi. 8903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ test(edx, Immediate(kSmiTagMask)); 8913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(zero, &slow); 8923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Get the map from the receiver. 8936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); 8943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the receiver does not require access checks. We need 8953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // to do this because this generic stub does not perform map checks. 8966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ movzx_b(ebx, FieldOperand(edi, Map::kBitFieldOffset)); 8973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); 8983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_zero, &slow); 8993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the key is a smi. 9006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(ecx, Immediate(kSmiTagMask)); 9013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_zero, &slow); 9023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Get the instance type from the map of the receiver. 9036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CmpInstanceType(edi, JS_OBJECT_TYPE); 9043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, &slow); 9053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the elements array is the appropriate type of 9073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ExternalArray. 9083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // eax: value 9096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver, a JSObject 9106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: key, a smi 9116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 9126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CheckMap(edi, Handle<Map>(Heap::MapForExternalArrayType(array_type)), 9136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block &slow, true); 9143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the index is in range. 9166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ebx, ecx); 9176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ SmiUntag(ebx); 9186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(ebx, FieldOperand(edi, ExternalArray::kLengthOffset)); 9193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Unsigned comparison catches both negative and too-large values. 9203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(above_equal, &slow); 9213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Handle both smis and HeapNumbers in the fast path. Go to the 9233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // runtime for all other kinds of values. 9243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // eax: value 9256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver 9266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: key 9276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edi: elements array 9283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ebx: untagged index 9293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ test(eax, Immediate(kSmiTagMask)); 9303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, &check_heap_number); 9313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // smi case 9326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ecx, eax); // Preserve the value in eax. Key is no longer needed. 9336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ SmiUntag(ecx); 9346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); 9353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ecx: base pointer of external storage 9363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block switch (array_type) { 9373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalByteArray: 9383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedByteArray: 9396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov_b(Operand(edi, ebx, times_1, 0), ecx); 9403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 9413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalShortArray: 9423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedShortArray: 9436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov_w(Operand(edi, ebx, times_2, 0), ecx); 9443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 9453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalIntArray: 9463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedIntArray: 9476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(Operand(edi, ebx, times_4, 0), ecx); 9483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 9493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalFloatArray: 9503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Need to perform int-to-float conversion. 9516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(ecx); 9523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fild_s(Operand(esp, 0)); 9536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(ecx); 9546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ fstp_s(Operand(edi, ebx, times_4, 0)); 9553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 9563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block default: 9573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block UNREACHABLE(); 9583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 9593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 9606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret(0); // Return the original value. 9613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&check_heap_number); 9636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // eax: value 9646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edx: receiver 9656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: key 9666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edi: elements array 9676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ebx: untagged index 9683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 9693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Immediate(Factory::heap_number_map())); 9703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, &slow); 9713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // The WebGL specification leaves the behavior of storing NaN and 9733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // +/-Infinity into integer arrays basically undefined. For more 9743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // reproducible behavior, convert these to zero. 9753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); 9766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); 9773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ebx: untagged index 9786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // edi: base pointer of external storage 9793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // top of FPU stack: value 9803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (array_type == kExternalFloatArray) { 9816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ fstp_s(Operand(edi, ebx, times_4, 0)); 9823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ret(0); 9833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 9843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Need to perform float-to-int conversion. 9853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Test the top of the FP stack for NaN. 9863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label is_nan; 9873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fucomi(0); 9883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(parity_even, &is_nan); 9893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (array_type != kExternalUnsignedIntArray) { 9916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(ecx); // Make room on stack 9923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fistp_s(Operand(esp, 0)); 9936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(ecx); 9943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 9953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // fistp stores values as signed integers. 9963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // To represent the entire range, we need to store as a 64-bit 9973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // int and discard the high 32 bits. 9986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ sub(Operand(esp), Immediate(2 * kPointerSize)); 9993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fistp_d(Operand(esp, 0)); 10006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(ecx); 10016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ add(Operand(esp), Immediate(kPointerSize)); 10023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 10036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ecx: untagged integer value 10043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block switch (array_type) { 10053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalByteArray: 10063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedByteArray: 10076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov_b(Operand(edi, ebx, times_1, 0), ecx); 10083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 10093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalShortArray: 10103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedShortArray: 10116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov_w(Operand(edi, ebx, times_2, 0), ecx); 10123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 10133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalIntArray: 10143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedIntArray: { 10153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // We also need to explicitly check for +/-Infinity. These are 10163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // converted to MIN_INT, but we need to be careful not to 10173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // confuse with legal uses of MIN_INT. 10183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label not_infinity; 10193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // This test would apparently detect both NaN and Infinity, 10203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // but we've already checked for NaN using the FPU hardware 10213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // above. 10226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov_w(edx, FieldOperand(eax, HeapNumber::kValueOffset + 6)); 10236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ and_(edx, 0x7FF0); 10246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(edx, 0x7FF0); 10253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, ¬_infinity); 10266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ecx, 0); 10273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(¬_infinity); 10286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(Operand(edi, ebx, times_4, 0), ecx); 10293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 10303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 10313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block default: 10323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block UNREACHABLE(); 10333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 10343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 10356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret(0); // Return original value. 10363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&is_nan); 10383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ffree(); 10393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fincstp(); 10403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block switch (array_type) { 10413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalByteArray: 10423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedByteArray: 10436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov_b(Operand(edi, ebx, times_1, 0), 0); 10443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 10453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalShortArray: 10463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedShortArray: 10476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ xor_(ecx, Operand(ecx)); 10486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov_w(Operand(edi, ebx, times_2, 0), ecx); 10493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 10503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalIntArray: 10513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedIntArray: 10526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(Operand(edi, ebx, times_4, 0), Immediate(0)); 10533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 10543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block default: 10553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block UNREACHABLE(); 10563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 10573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 10586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret(0); // Return the original value. 10593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 10603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Slow case: call runtime. 10623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&slow); 1063402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateRuntimeSetProperty(masm); 10643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 10653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 10663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Defined in ic.cc. 1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* CallIC_Miss(Arguments args); 1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { 1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1072e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 1073e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 1074e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1075e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 1076e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label number, non_number, non_string, boolean, probe, miss; 1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver of the function from the stack; 1 ~ return address. 1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the stub cache. 1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Flags flags = 1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc); 1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, eax); 1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the stub cache probing failed, the receiver might be a value. 1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // For value objects, we use the map of the prototype objects for 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the corresponding JSValue for the cache and that is what we need 1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to probe. 1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for number. 1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(edx, Immediate(kSmiTagMask)); 1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &number, not_taken); 1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ebx); 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &non_number, taken); 1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&number); 1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadGlobalFunctionPrototype( 1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm, Context::NUMBER_FUNCTION_INDEX, edx); 1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&probe); 1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for string. 1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&non_number); 1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(ebx, FIRST_NONSTRING_TYPE); 1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &non_string, taken); 1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadGlobalFunctionPrototype( 1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm, Context::STRING_FUNCTION_INDEX, edx); 1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&probe); 1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for boolean. 1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&non_string); 1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(edx, Factory::true_value()); 1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &boolean, not_taken); 1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(edx, Factory::false_value()); 1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss, taken); 1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&boolean); 1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadGlobalFunctionPrototype( 1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm, Context::BOOLEAN_FUNCTION_INDEX, edx); 1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the stub cache for the value object. 1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&probe); 1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg); 1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cache miss: Jump to runtime. 1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 1127e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke GenerateMiss(masm, argc); 1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GenerateNormalHelper(MacroAssembler* masm, 1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int argc, 1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_global_object, 1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 1135e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------- S t a t e ------------- 1136e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 1137e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- edx : receiver 1138e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 1139e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1140e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 1141e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 1142e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------------------------------- 1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1144e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Search dictionary - put result in register edi. 1145e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(edi, edx); 1146402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateDictionaryLoad(masm, miss, edx, ecx, eax, edi, ebx, CHECK_DICTIONARY); 1147e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1148e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the result is not a smi. 1149e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ test(edi, Immediate(kSmiTagMask)); 1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, miss, not_taken); 1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1152e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the value is a JavaScript function, fetching its map into eax. 1153e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax); 1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, miss, not_taken); 1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1156e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Patch the receiver on stack with the global proxy if necessary. 1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (is_global_object) { 1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the function. 1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount actual(argc); 1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeFunction(edi, actual, JUMP_FUNCTION); 1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CallIC::GenerateNormal(MacroAssembler* masm, int argc) { 1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1170e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 1171e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 1172e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1173e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 1174e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss, global_object, non_global_object; 1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver of the function from the stack; 1 ~ return address. 1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(edx, Immediate(kSmiTagMask)); 1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &miss, not_taken); 1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver is a valid JS object. 1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); 1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(eax, FieldOperand(ebx, Map::kInstanceTypeOffset)); 1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, FIRST_JS_OBJECT_TYPE); 1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(below, &miss, not_taken); 1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If this assert fails, we have to check upper bound too. 1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for access to global object. 1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, JS_GLOBAL_OBJECT_TYPE); 1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &global_object); 1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, JS_BUILTINS_OBJECT_TYPE); 1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &non_global_object); 1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Accessing global object: Load and invoke. 1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&global_object); 1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the global object does not require access checks. 1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset)); 1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); 1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss, not_taken); 1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateNormalHelper(masm, argc, true, &miss); 1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Accessing non-global object: Check for access to global proxy. 1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label global_proxy, invoke; 1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&non_global_object); 1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, JS_GLOBAL_PROXY_TYPE); 1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &global_proxy, not_taken); 1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the non-global, non-global-proxy object does not 1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // require access checks. 1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset)); 1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); 1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss, not_taken); 1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&invoke); 1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateNormalHelper(masm, argc, false, &miss); 1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Global object proxy access: Check access rights. 1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&global_proxy); 1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CheckAccessGlobalProxy(edx, eax, &miss); 1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&invoke); 1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cache miss: Jump to runtime. 1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 1228e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke GenerateMiss(masm, argc); 1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1232e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid CallIC::GenerateMiss(MacroAssembler* masm, int argc) { 1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1234e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 1235e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 1236e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1237e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 1238e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver of the function from the stack; 1 ~ return address. 1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Enter an internal frame. 1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ EnterInternalFrame(); 1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push the receiver and the name of the function. 1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(edx); 1249e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(ecx); 1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call the entry. 1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CEntryStub stub(1); 1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, Immediate(2)); 1254e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(ebx, Immediate(ExternalReference(IC_Utility(kCallIC_Miss)))); 1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CallStub(&stub); 1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move result to edi and exit the internal frame. 1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edi, eax); 1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LeaveInternalFrame(); 1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the receiver is a global object of some sort. 1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label invoke, global; 1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); // receiver 1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(edx, Immediate(kSmiTagMask)); 1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &invoke, not_taken); 1266e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); 1267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 1268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(ebx, JS_GLOBAL_OBJECT_TYPE); 1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &global); 1270e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(ebx, JS_BUILTINS_OBJECT_TYPE); 1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &invoke); 1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack. 1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&global); 1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the function. 1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount actual(argc); 1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&invoke); 1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeFunction(edi, actual, JUMP_FUNCTION); 1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Defined in ic.cc. 1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* LoadIC_Miss(Arguments args); 1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateMegamorphic(MacroAssembler* masm) { 1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1290402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the stub cache. 1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, 1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NOT_IN_LOOP, 1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MONOMORPHIC); 1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCache::GenerateProbe(masm, flags, eax, ecx, ebx, edx); 1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cache miss: Jump to runtime. 1302402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateMiss(masm); 1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateNormal(MacroAssembler* masm) { 1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1308402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss, probe, global; 1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(eax, Immediate(kSmiTagMask)); 1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &miss, not_taken); 1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver is a valid JS object. 1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(edx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(edx, FIRST_JS_OBJECT_TYPE); 1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(less, &miss, not_taken); 1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If this assert fails, we have to check upper bound too. 1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for access to global object (unlikely). 1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(edx, JS_GLOBAL_PROXY_TYPE); 1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &global, not_taken); 1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for non-global object that requires access check. 1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset)); 1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); 1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &miss, not_taken); 1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Search the dictionary placing the result in eax. 1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&probe); 1338402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateDictionaryLoad(masm, 1339402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu &miss, 1340402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu eax, 1341402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ecx, 1342402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu edx, 1343402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu edi, 1344402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ebx, 1345402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu CHECK_DICTIONARY); 1346402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, edi); 1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Global object access: Check access rights. 1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&global); 1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CheckAccessGlobalProxy(eax, edx, &miss); 1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&probe); 1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cache miss: Restore receiver from stack and jump to runtime. 1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 1356402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateMiss(masm); 1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateMiss(MacroAssembler* masm) { 1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1362402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); 1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(eax); // receiver 1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); // name 1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); // return address 1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform tail call to the entry. 13736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss)); 13746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(ref, 2, 1); 1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// One byte opcode for test eax,0xXXXXXXXX. 1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const byte kTestEaxByte = 0xA9; 1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::ClearInlinedVersion(Address address) { 1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reset the map check of the inlined inobject property load (if 1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // present) to guarantee failure by holding an invalid map (the null 1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // value). The offset can be patched to anything. 1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PatchInlinedLoad(address, Heap::null_value(), kMaxInt); 1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid KeyedLoadIC::ClearInlinedVersion(Address address) { 1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Insert null as the map to check for to make sure the map check fails 1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sending control flow to the IC instead of the inlined version. 1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PatchInlinedLoad(address, Heap::null_value()); 1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid KeyedStoreIC::ClearInlinedVersion(Address address) { 1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Insert null as the elements map to check for. This will make 1399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sure that the elements fast-case map check fails so that control 1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // flows to the IC instead of the inlined version. 1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PatchInlinedStore(address, Heap::null_value()); 1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid KeyedStoreIC::RestoreInlinedVersion(Address address) { 1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore the fast-case elements map check so that the inlined 1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // version can be used again. 1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PatchInlinedStore(address, Heap::fixed_array_map()); 1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { 1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The address of the instruction following the call. 1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address test_instruction_address = 1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block address + Assembler::kCallTargetAddressOffset; 1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the instruction following the call is not a test eax, nothing 1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // was inlined. 1418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*test_instruction_address != kTestEaxByte) return false; 1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address delta_address = test_instruction_address + 1; 1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The delta to the start of the map check instruction. 1422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int delta = *reinterpret_cast<int*>(delta_address); 1423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The map address is the last 4 bytes of the 7-byte 1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // operand-immediate compare instruction, so we add 3 to get the 1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // offset to the last 4 bytes. 1427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address map_address = test_instruction_address + delta + 3; 1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *(reinterpret_cast<Object**>(map_address)) = map; 1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The offset is in the last 4 bytes of a six byte 1431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // memory-to-register move instruction, so we add 2 to get the 1432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // offset to the last 4 bytes. 1433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address offset_address = 1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block test_instruction_address + delta + kOffsetToLoadInstruction + 2; 1435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; 1436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool PatchInlinedMapCheck(Address address, Object* map) { 1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address test_instruction_address = 1442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block address + Assembler::kCallTargetAddressOffset; 1443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The keyed load has a fast inlined case if the IC call instruction 1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is immediately followed by a test instruction. 1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*test_instruction_address != kTestEaxByte) return false; 1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fetch the offset from the test instruction to the map cmp 1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // instruction. This offset is stored in the last 4 bytes of the 5 1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // byte test instruction. 1450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address delta_address = test_instruction_address + 1; 1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int delta = *reinterpret_cast<int*>(delta_address); 1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the map address. The map address is in the last 4 bytes 1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // of the 7-byte operand-immediate compare instruction, so we add 3 1454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to the offset to get the map address. 1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address map_address = test_instruction_address + delta + 3; 1456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the map check. 1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *(reinterpret_cast<Object**>(map_address)) = map; 1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool KeyedLoadIC::PatchInlinedLoad(Address address, Object* map) { 1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return PatchInlinedMapCheck(address, map); 1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool KeyedStoreIC::PatchInlinedStore(Address address, Object* map) { 1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return PatchInlinedMapCheck(address, map); 1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Defined in ic.cc. 1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadIC_Miss(Arguments args); 1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { 1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1478402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 1479402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1483402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(ebx); 1484402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(edx); // receiver 1485402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(eax); // name 1486402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(ebx); // return address 1487402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1488402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Perform tail call to the entry. 14896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss)); 14906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(ref, 2, 1); 1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1494402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { 1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1496402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 1497402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); 1502402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(edx); // receiver 1503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(eax); // name 1504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); // return address 1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform tail call to the entry. 15076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 1508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StoreIC::GenerateMegamorphic(MacroAssembler* masm) { 1512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 15154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- edx : receiver 1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, 1520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NOT_IN_LOOP, 1521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MONOMORPHIC); 1522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg); 1523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cache miss: Jump to runtime. 15254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke GenerateMiss(masm); 1526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid StoreIC::GenerateMiss(MacroAssembler* masm) { 1530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 1532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 15334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- edx : receiver 1534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); 15384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(edx); 1539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); 1540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(eax); 1541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); 1542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform tail call to the entry. 15446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_Miss)); 15456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(ref, 3, 1); 15466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 15476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15496ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid StoreIC::GenerateArrayLength(MacroAssembler* masm) { 15506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 15516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- eax : value 15526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : name 15536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- edx : receiver 15546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[0] : return address 15556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 15566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // 15576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // This accepts as a receiver anything JSObject::SetElementsLength accepts 15586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // (currently anything except for external and pixel arrays which means 15596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // anything with elements of FixedArray type.), but currently is restricted 15606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // to JSArray. 15616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Value must be a number, but only smis are accepted as the most common case. 15626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss; 15646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register receiver = edx; 15666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register value = eax; 15676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch = ebx; 15686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the receiver isn't a smi. 15706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(receiver, Immediate(kSmiTagMask)); 15716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(zero, &miss, not_taken); 15726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the object is a JS array. 15746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); 15756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_equal, &miss, not_taken); 15766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that elements are FixedArray. 15786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(scratch, FieldOperand(receiver, JSArray::kElementsOffset)); 15796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch); 15806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_equal, &miss, not_taken); 15816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that value is a smi. 15836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(value, Immediate(kSmiTagMask)); 15846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_zero, &miss, not_taken); 15856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Prepare tail call to StoreIC_ArrayLength. 15876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(scratch); 15886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(receiver); 15896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(value); 15906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(scratch); // return address 15916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_ArrayLength)); 15936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(ref, 2, 1); 15946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss); 15966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GenerateMiss(masm); 1598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Defined in ic.cc. 1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedStoreIC_Miss(Arguments args); 1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1604402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) { 1605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 16076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : key 16086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- edx : receiver 1609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(ebx); 16136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(edx); 1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); 16156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(eax); 16166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(ebx); 1617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to runtime routine. 16196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallRuntime(Runtime::kSetProperty, 3, 1); 1620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1623402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { 1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 16266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : key 16276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- edx : receiver 1628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(ebx); 16326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(edx); 1633402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(ecx); 16346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(eax); 16356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(ebx); 1636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to runtime routine. 16386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); 16396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(ref, 3, 1); 1640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 1643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 1646