ic-ia32.cc revision 402d937239b0e2fd11bf2f4fe972ad78aa9fd481
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 // Test the has_named_interceptor bit in the map. 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(FieldOperand(r0, Map::kInstanceAttributesOffset), 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(1 << (Map::kHasNamedInterceptor + (3 * 8)))); 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to miss if the interceptor bit is set. 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, miss_label, not_taken); 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Bail out if we have a JS global proxy object. 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(r0, FieldOperand(r0, Map::kInstanceTypeOffset)); 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, JS_GLOBAL_PROXY_TYPE); 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, miss_label, not_taken); 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Possible work-around for http://crbug.com/16276. 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, JS_GLOBAL_OBJECT_TYPE); 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, miss_label, not_taken); 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, JS_BUILTINS_OBJECT_TYPE); 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, miss_label, not_taken); 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 94e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Load properties array. 95402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(r0, FieldOperand(receiver, JSObject::kPropertiesOffset)); 96e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 97e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the properties array is a dictionary. 98e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (check_dictionary == CHECK_DICTIONARY) { 99e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(FieldOperand(r0, HeapObject::kMapOffset), 100e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Immediate(Factory::hash_table_map())); 101e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_equal, miss_label); 102e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the capacity mask. 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kCapacityOffset = 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StringDictionary::kHeaderSize + 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StringDictionary::kCapacityIndex * kPointerSize; 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, FieldOperand(r0, kCapacityOffset)); 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ shr(r2, kSmiTagSize); // convert smi to int 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ dec(r2); 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Generate an unrolled loop that performs a few probes before 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // giving up. Measurements done on Gmail indicate that 2 probes 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // cover ~93% of loads from dictionaries. 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kProbes = 4; 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kElementsStartOffset = 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StringDictionary::kHeaderSize + 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StringDictionary::kElementsStartIndex * kPointerSize; 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < kProbes; i++) { 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the masked index: (hash + i + i * i) & mask. 121d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r1, FieldOperand(name, String::kHashFieldOffset)); 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ shr(r1, String::kHashShift); 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (i > 0) { 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(Operand(r1), Immediate(StringDictionary::GetProbeOffset(i))); 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(r1, Operand(r2)); 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Scale the index by multiplying by the entry size. 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(StringDictionary::kEntrySize == 3); 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(r1, Operand(r1, r1, times_2, 0)); // r1 = r1 * 3 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the key is identical to the name. 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(name, 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand(r0, r1, times_4, kElementsStartOffset - kHeapObjectTag)); 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (i != kProbes - 1) { 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &done, taken); 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, miss_label, not_taken); 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the value is a normal property. 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&done); 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(Operand(r0, r1, times_4, kDetailsOffset - kHeapObjectTag), 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, miss_label, not_taken); 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the value at the masked, scaled index. 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kValueOffset = kElementsStartOffset + kPointerSize; 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r1, Operand(r0, r1, times_4, kValueOffset - kHeapObjectTag)); 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The offset from the inlined patch site to the start of the 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// inlined load instruction. It is 7 bytes (test eax, imm) plus 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6 bytes (jne slow_label). 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int LoadIC::kOffsetToLoadInstruction = 13; 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateArrayLength(MacroAssembler* masm) { 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 163402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadArrayLength(masm, eax, edx, &miss); 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateStringLength(MacroAssembler* masm) { 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 177402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 183402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu StubCompiler::GenerateLoadStringLength(masm, eax, edx, ebx, &miss); 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) { 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 191402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadFunctionPrototype(masm, eax, edx, ebx, &miss); 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 205402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 206402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 209e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label slow, check_string, index_int, index_string; 210e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label check_pixel_array, probe_dictionary; 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object isn't a smi. 213402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ test(edx, Immediate(kSmiTagMask)); 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &slow, not_taken); 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the map of the receiver. 217402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 218d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 219d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Check bit field. 220402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset)); 221d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ test(ebx, Immediate(kSlowCaseBitFieldMask)); 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &slow, not_taken); 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is some kind of JS object EXCEPT JS Value type. 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // In the case that the object is a value-wrapper object, 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // we enter the runtime system to make sure that indexing 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // into string objects work as intended. 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); 228402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CmpInstanceType(ecx, JS_OBJECT_TYPE); 229402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ j(below, &slow, not_taken); 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the key is a smi. 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(eax, Immediate(kSmiTagMask)); 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &check_string, not_taken); 233402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ebx, eax); 234402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ SmiUntag(ebx); 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the elements array of the object. 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&index_int); 237402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is in fast mode (not dictionary). 239402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CheckMap(ecx, Factory::fixed_array_map(), &check_pixel_array, true); 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the key (index) is within bounds. 241402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(ebx, FieldOperand(ecx, FixedArray::kLengthOffset)); 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &slow); 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fast case: Do the load. 244402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, FieldOperand(ecx, ebx, times_4, FixedArray::kHeaderSize)); 245402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(Operand(ecx), Immediate(Factory::the_hole_value())); 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // In case the loaded value is the_hole we have to consult GetProperty 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to ensure the prototype chain is searched. 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &slow); 249402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, ecx); 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&check_pixel_array); 254402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Check whether the elements is a pixel array. 255402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // edx: receiver 256402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ebx: untagged index 257402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // eax: key 258402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ecx: elements 259402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CheckMap(ecx, Factory::pixel_array_map(), &slow, true); 260402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(ebx, FieldOperand(ecx, PixelArray::kLengthOffset)); 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &slow); 262402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, FieldOperand(ecx, PixelArray::kExternalPointerOffset)); 263402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(eax, Operand(eax, ebx, times_1, 0)); 264402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ SmiTag(eax); 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&slow); 268402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Slow case: jump to runtime. 269402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // edx: receiver 270402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // eax: key 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); 272402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateRuntimeGetProperty(masm); 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&check_string); 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The key is not a smi. 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Is it a string? 277402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // edx: receiver 278402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // eax: key 279402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ecx); 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &slow); 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Is the string an array index, with cached numeric value? 282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(ebx, FieldOperand(eax, String::kHashFieldOffset)); 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(ebx, Immediate(String::kIsArrayIndexMask)); 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &index_string, not_taken); 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 286e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Is the string a symbol? 287402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(ebx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 288e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(kSymbolTag != 0); 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(ebx, Immediate(kIsSymbolMask)); 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &slow, not_taken); 291e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 292e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // If the receiver is a fast-case object, check the keyed lookup 293402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // cache. Otherwise probe the dictionary. 294402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset)); 295e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 296e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Immediate(Factory::hash_table_map())); 297e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, &probe_dictionary); 298e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Load the map of the receiver, compute the keyed lookup cache hash 300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // based on 32 bits of the map pointer and the string hash. 301402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); 302402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, ebx); 303402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ shr(ecx, KeyedLookupCache::kMapHashShift); 304402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(edi, FieldOperand(eax, String::kHashFieldOffset)); 305402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ shr(edi, String::kHashShift); 306402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ xor_(ecx, Operand(edi)); 307402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ and_(ecx, KeyedLookupCache::kCapacityMask); 308e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 309e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Load the key (consisting of map and symbol) from the cache and 310e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // check for match. 311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ExternalReference cache_keys 312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke = ExternalReference::keyed_lookup_cache_keys(); 313402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(edi, ecx); 314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ shl(edi, kPointerSizeLog2 + 1); 315e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys)); 316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_equal, &slow); 317e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ add(Operand(edi), Immediate(kPointerSize)); 318402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(eax, Operand::StaticArray(edi, times_1, cache_keys)); 319e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_equal, &slow); 320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 321e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Get field offset and check that it is an in-object property. 322402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // edx : receiver 323402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ebx : receiver's map 324402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // eax : key 325402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ecx : lookup cache index 326e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ExternalReference cache_field_offsets 327e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke = ExternalReference::keyed_lookup_cache_field_offsets(); 328402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(edi, 329402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Operand::StaticArray(ecx, times_pointer_size, cache_field_offsets)); 330402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(ecx, FieldOperand(ebx, Map::kInObjectPropertiesOffset)); 331402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(edi, Operand(ecx)); 332e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(above_equal, &slow); 333e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 334e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Load in-object property. 335402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ sub(edi, Operand(ecx)); 336402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset)); 337402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ add(ecx, Operand(edi)); 338402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, FieldOperand(edx, ecx, times_pointer_size, 0)); 339e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ret(0); 340e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Do a quick inline probe of the receiver's dictionary, if it 342e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // exists. 343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&probe_dictionary); 344e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke GenerateDictionaryLoad(masm, 345e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke &slow, 346e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke edx, 347e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke eax, 348402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ebx, 349402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ecx, 350402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu edi, 351e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke DICTIONARY_CHECK_DONE); 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, Operand(ecx)); 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 355e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 356d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // If the hash field contains an array index pick it out. The assert checks 357d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // that the constants for the maximum number of digits for an array index 358d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // cached in the hash field and the number of bits reserved for it does not 359d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // conflict. 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < 361d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block (1 << String::kArrayIndexValueBits)); 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&index_string); 363402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ and_(ebx, String::kArrayIndexHashMask); 364402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ shr(ebx, String::kHashShift); 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&index_int); 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 369e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid KeyedLoadIC::GenerateString(MacroAssembler* masm) { 370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------- S t a t e ------------- 371402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 372402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 373e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------------------------------- 375e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label miss, index_ok; 376e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 377e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Pop return address. 378e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Performing the load early is better in the common case. 379402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(ebx); 380e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 381402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ test(edx, Immediate(kSmiTagMask)); 382e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(zero, &miss); 383402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 384e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 385e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ test(ecx, Immediate(kIsNotStringMask)); 386e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_zero, &miss); 387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 388e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check if key is a smi or a heap number. 389402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ test(eax, Immediate(kSmiTagMask)); 390e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(zero, &index_ok); 391402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 392e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(ecx, Factory::heap_number_map()); 393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_equal, &miss); 394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 395e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&index_ok); 396402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Push receiver and key on the stack, and make a tail call. 397402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(edx); // receiver 398402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(eax); // key 399402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(ebx); // return address 400e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ InvokeBuiltin(Builtins::STRING_CHAR_AT, JUMP_FUNCTION); 401e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 402e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&miss); 403402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(ebx); 404e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke GenerateMiss(masm); 405e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 406e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 407e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm, 4093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ExternalArrayType array_type) { 4103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ----------- S t a t e ------------- 411402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 412402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 4133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // -- esp[0] : return address 4143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ----------------------------------- 4153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label slow, failed_allocation; 4163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the object isn't a smi. 418402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ test(edx, Immediate(kSmiTagMask)); 4193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(zero, &slow, not_taken); 4203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the key is a smi. 4223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ test(eax, Immediate(kSmiTagMask)); 4233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_zero, &slow, not_taken); 4243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Get the map of the receiver. 426402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 4273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the receiver does not require access checks. We need 4283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // to check this explicitly since this generic stub does not perform 4293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // map checks. 430402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset)); 4313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); 4323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_zero, &slow, not_taken); 4333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 434402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CmpInstanceType(ecx, JS_OBJECT_TYPE); 4353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, &slow, not_taken); 4363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the elements array is the appropriate type of 4383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ExternalArray. 439402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); 4403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Handle<Map> map(Heap::MapForExternalArrayType(array_type)); 441402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 4423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Immediate(map)); 4433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, &slow, not_taken); 4443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 445402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // eax: key, known to be a smi. 446402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // edx: receiver, known to be a JSObject. 447402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ebx: elements object, known to be an external array. 4483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the index is in range. 449402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, eax); 450402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ SmiUntag(ecx); // Untag the index. 451402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset)); 4523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Unsigned comparison catches both negative and too-large values. 4533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(above_equal, &slow); 4543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 455402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset)); 456402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ebx: base pointer of external storage 4573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block switch (array_type) { 4583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalByteArray: 459402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movsx_b(ecx, Operand(ebx, ecx, times_1, 0)); 4603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 4613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedByteArray: 462402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(ecx, Operand(ebx, ecx, times_1, 0)); 4633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 4643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalShortArray: 465402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movsx_w(ecx, Operand(ebx, ecx, times_2, 0)); 4663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 4673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedShortArray: 468402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_w(ecx, Operand(ebx, ecx, times_2, 0)); 4693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 4703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalIntArray: 4713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedIntArray: 472402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, Operand(ebx, ecx, times_4, 0)); 4733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 4743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalFloatArray: 475402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ fld_s(Operand(ebx, ecx, times_4, 0)); 4763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 4773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block default: 4783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block UNREACHABLE(); 4793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 4803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 4813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // For integer array types: 483402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ecx: value 4843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // For floating-point array type: 4853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // FP(0): value 4863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (array_type == kExternalIntArray || 4883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block array_type == kExternalUnsignedIntArray) { 4893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // For the Int and UnsignedInt array types, we need to see whether 4903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // the value can be represented in a Smi. If not, we need to convert 4913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // it to a HeapNumber. 4923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label box_int; 4933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (array_type == kExternalIntArray) { 494402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(ecx, 0xC0000000); 495402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ j(sign, &box_int); 4963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 4973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT_EQ(array_type, kExternalUnsignedIntArray); 4983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // The test is different for unsigned int values. Since we need 499402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // the value to be in the range of a positive smi, we can't 5003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // handle either of the top two bits being set in the value. 501402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ test(ecx, Immediate(0xC0000000)); 5023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_zero, &box_int); 5033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 5043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 505402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, ecx); 506402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ SmiTag(eax); 5073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ret(0); 5083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 5093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&box_int); 5103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 5113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Allocate a HeapNumber for the int and perform int-to-double 5123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // conversion. 5133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (array_type == kExternalIntArray) { 514402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(ecx); 5153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fild_s(Operand(esp, 0)); 516402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(ecx); 5173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 5183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ASSERT(array_type == kExternalUnsignedIntArray); 5193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Need to zero-extend the value. 5203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // There's no fild variant for unsigned values, so zero-extend 5213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // to a 64-bit int manually. 5223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(Immediate(0)); 523402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(ecx); 5243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fild_d(Operand(esp, 0)); 525402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(ecx); 526402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(ecx); 5273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 5283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // FP(0): value 529402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); 5303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Set the value. 531402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, ecx); 5323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 5333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ret(0); 5343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (array_type == kExternalFloatArray) { 5353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // For the floating-point array type, we need to always allocate a 5363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // HeapNumber. 537402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); 5383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Set the value. 539402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, ecx); 5403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 5413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ret(0); 5423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 543402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, ecx); 544402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ SmiTag(eax); 5453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ret(0); 5463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 5473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 5483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If we fail allocation of the HeapNumber, we still have a value on 5493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // top of the FPU stack. Remove it. 5503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&failed_allocation); 5513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ffree(); 5523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fincstp(); 5533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Fall through to slow case. 5543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 555402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Slow case: Load key and receiver from stack and jump to runtime. 5563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&slow); 5573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1); 558402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateRuntimeGetProperty(masm); 559402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 560402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 561402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 562402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { 563402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------- S t a t e ------------- 564402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 565402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 566402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- esp[0] : return address 567402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------------------------------- 568402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label slow; 569402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 570402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Check that the receiver isn't a smi. 571402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ test(edx, Immediate(kSmiTagMask)); 572402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ j(zero, &slow, not_taken); 573402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 574402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Check that the key is a smi. 575402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ test(eax, Immediate(kSmiTagMask)); 576402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ j(not_zero, &slow, not_taken); 577402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 578402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Get the map of the receiver. 579402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 580402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 581402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Check that it has indexed interceptor and access checks 582402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // are not enabled for this object. 583402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ movzx_b(ecx, FieldOperand(ecx, Map::kBitFieldOffset)); 584402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ and_(Operand(ecx), Immediate(kSlowCaseBitFieldMask)); 585402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(Operand(ecx), Immediate(1 << Map::kHasIndexedInterceptor)); 586402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ j(not_zero, &slow, not_taken); 587402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 588402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Everything is fine, call runtime. 589402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(ecx); 590402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(edx); // receiver 591402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(eax); // key 592402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(ecx); // return address 593402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 594402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Perform tail call to the entry. 595402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ TailCallRuntime(ExternalReference( 596402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu IC_Utility(kKeyedLoadPropertyWithInterceptor)), 2, 1); 597402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 598402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ bind(&slow); 599402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateMiss(masm); 6003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 6013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 6023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { 604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[4] : key 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[8] : receiver 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label slow, fast, array, extra, check_pixel_array; 611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver from the stack. 613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, 2 * kPointerSize)); // 2 ~ return address, key 614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object isn't a smi. 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(edx, Immediate(kSmiTagMask)); 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &slow, not_taken); 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the map from the receiver. 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver does not require access checks. We need 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to do this because this generic stub does not perform map checks. 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset)); 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); 623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &slow, not_taken); 624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the key from the stack. 625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, Operand(esp, 1 * kPointerSize)); // 1 ~ return address 626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the key is a smi. 627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(ebx, Immediate(kSmiTagMask)); 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &slow, not_taken); 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the instance type from the map of the receiver. 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the object is a JS array or not. 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(ecx, JS_ARRAY_TYPE); 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &array); 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is some kind of JS object. 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(ecx, FIRST_JS_OBJECT_TYPE); 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(less, &slow, not_taken); 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Object case: Check key against length in the elements array. 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: value 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edx: JSObject 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ebx: index (as a smi) 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is in fast mode (not dictionary). 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(Factory::fixed_array_map())); 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &check_pixel_array, not_taken); 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Untag the key (for checking against untagged length in the fixed array). 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(ebx)); 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sar(edx, kSmiTagSize); // untag the index and use it for the comparison 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(edx, FieldOperand(ecx, Array::kLengthOffset)); 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: value 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ecx: FixedArray 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ebx: index (as a smi) 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(below, &fast, taken); 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Slow case: call runtime. 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&slow); 658402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateRuntimeSetProperty(masm); 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check whether the elements is a pixel array. 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: value 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ecx: elements array 663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ebx: index (as a smi) 664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&check_pixel_array); 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(Factory::pixel_array_map())); 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &slow); 668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the value is a smi. If a conversion is needed call into the 669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // runtime to convert and clamp. 670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(eax, Immediate(kSmiTagMask)); 671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &slow); 672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sar(ebx, kSmiTagSize); // Untag the index. 673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(ebx, FieldOperand(ecx, PixelArray::kLengthOffset)); 674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &slow); 675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, eax); // Save the value. 676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sar(eax, kSmiTagSize); // Untag the value. 677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { // Clamp the value to [0..255]. 6783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label done; 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(eax, Immediate(0xFFFFFF00)); 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &done); 6813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ setcc(negative, eax); // 1 if negative, 0 if positive. 6823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ dec_b(eax); // 0 if negative, 255 if positive. 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&done); 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ecx, FieldOperand(ecx, PixelArray::kExternalPointerOffset)); 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov_b(Operand(ecx, ebx, times_1, 0), eax); 687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, edx); // Return the original value. 688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Extra capacity case: Check if there is extra capacity to 691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // perform the store and update the length. Used for adding one 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // element to the array by writing to array[array.length]. 693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&extra); 694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: value 695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edx: JSArray 696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ecx: FixedArray 697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ebx: index (as a smi) 698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // flags: compare (ebx, edx.length()) 699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &slow, not_taken); // do not leave holes in the array 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sar(ebx, kSmiTagSize); // untag 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(ebx, FieldOperand(ecx, Array::kLengthOffset)); 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &slow, not_taken); 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore tag and increment. 704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(ebx, Operand(ebx, times_2, 1 << kSmiTagSize)); 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(FieldOperand(edx, JSArray::kLengthOffset), ebx); 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(Operand(ebx), Immediate(1 << kSmiTagSize)); // decrement ebx again 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&fast); 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Array case: Get the length and the elements array from the JS 710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // array. Check that the array is in fast mode; if it is the 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // length is always a smi. 712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&array); 713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: value 714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edx: JSArray 715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ebx: index (as a smi) 716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); 717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), 718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(Factory::fixed_array_map())); 719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &check_pixel_array); 720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the key against the length in the array, compute the 722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // address to store into and fall through to fast case. 723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(ebx, FieldOperand(edx, JSArray::kLengthOffset)); 724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &extra, not_taken); 725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fast case: Do the store. 727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fast); 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: value 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ecx: FixedArray 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ebx: index (as a smi) 731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(ecx, ebx, times_2, FixedArray::kHeaderSize - kHeapObjectTag), 732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block eax); 733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update write barrier for the elements array address. 734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(eax)); 735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ RecordWrite(ecx, 0, edx, ebx); 736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm, 7413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ExternalArrayType array_type) { 7423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ----------- S t a t e ------------- 7433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // -- eax : value 7443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // -- esp[0] : return address 7453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // -- esp[4] : key 7463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // -- esp[8] : receiver 7473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ----------------------------------- 7483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label slow, check_heap_number; 7493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Get the receiver from the stack. 7513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(edx, Operand(esp, 2 * kPointerSize)); 7523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the object isn't a smi. 7533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ test(edx, Immediate(kSmiTagMask)); 7543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(zero, &slow); 7553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Get the map from the receiver. 7563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 7573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the receiver does not require access checks. We need 7583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // to do this because this generic stub does not perform map checks. 7593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset)); 7603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); 7613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_zero, &slow); 7623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Get the key from the stack. 7633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(ebx, Operand(esp, 1 * kPointerSize)); // 1 ~ return address 7643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the key is a smi. 7653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ test(ebx, Immediate(kSmiTagMask)); 7663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_zero, &slow); 7673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Get the instance type from the map of the receiver. 7683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 7693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the object is a JS object. 7703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ cmp(ecx, JS_OBJECT_TYPE); 7713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, &slow); 7723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the elements array is the appropriate type of 7743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ExternalArray. 7753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // eax: value 7763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // edx: JSObject 7773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ebx: index (as a smi) 7783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); 7793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Handle<Map> map(Heap::MapForExternalArrayType(array_type)); 7803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), 7813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Immediate(map)); 7823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, &slow); 7833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Check that the index is in range. 7853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ sar(ebx, kSmiTagSize); // Untag the index. 7863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ cmp(ebx, FieldOperand(ecx, ExternalArray::kLengthOffset)); 7873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Unsigned comparison catches both negative and too-large values. 7883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(above_equal, &slow); 7893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Handle both smis and HeapNumbers in the fast path. Go to the 7913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // runtime for all other kinds of values. 7923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // eax: value 7933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ecx: elements array 7943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ebx: untagged index 7953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ test(eax, Immediate(kSmiTagMask)); 7963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, &check_heap_number); 7973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // smi case 7983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(edx, eax); // Save the value. 7993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ sar(eax, kSmiTagSize); // Untag the value. 8003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(ecx, FieldOperand(ecx, ExternalArray::kExternalPointerOffset)); 8013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ecx: base pointer of external storage 8023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block switch (array_type) { 8033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalByteArray: 8043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedByteArray: 8053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov_b(Operand(ecx, ebx, times_1, 0), eax); 8063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 8073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalShortArray: 8083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedShortArray: 8093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov_w(Operand(ecx, ebx, times_2, 0), eax); 8103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 8113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalIntArray: 8123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedIntArray: 8133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(Operand(ecx, ebx, times_4, 0), eax); 8143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 8153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalFloatArray: 8163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Need to perform int-to-float conversion. 8173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(eax); 8183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fild_s(Operand(esp, 0)); 8193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ pop(eax); 8203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fstp_s(Operand(ecx, ebx, times_4, 0)); 8213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 8223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block default: 8233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block UNREACHABLE(); 8243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 8253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 8263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(eax, edx); // Return the original value. 8273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ret(0); 8283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&check_heap_number); 8303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 8313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Immediate(Factory::heap_number_map())); 8323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, &slow); 8333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // The WebGL specification leaves the behavior of storing NaN and 8353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // +/-Infinity into integer arrays basically undefined. For more 8363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // reproducible behavior, convert these to zero. 8373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); 8383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(edx, eax); // Save the value. 8393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(ecx, FieldOperand(ecx, ExternalArray::kExternalPointerOffset)); 8403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ebx: untagged index 8413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // ecx: base pointer of external storage 8423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // top of FPU stack: value 8433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (array_type == kExternalFloatArray) { 8443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fstp_s(Operand(ecx, ebx, times_4, 0)); 8453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(eax, edx); // Return the original value. 8463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ret(0); 8473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 8483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Need to perform float-to-int conversion. 8493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Test the top of the FP stack for NaN. 8503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label is_nan; 8513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fucomi(0); 8523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(parity_even, &is_nan); 8533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (array_type != kExternalUnsignedIntArray) { 8553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(eax); // Make room on stack 8563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fistp_s(Operand(esp, 0)); 8573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ pop(eax); 8583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 8593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // fistp stores values as signed integers. 8603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // To represent the entire range, we need to store as a 64-bit 8613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // int and discard the high 32 bits. 8623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(eax); // Make room on stack 8633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ push(eax); // Make room on stack 8643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fistp_d(Operand(esp, 0)); 8653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ pop(eax); 8663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(Operand(esp, 0), eax); 8673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ pop(eax); 8683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 8693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // eax: untagged integer value 8703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block switch (array_type) { 8713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalByteArray: 8723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedByteArray: 8733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov_b(Operand(ecx, ebx, times_1, 0), eax); 8743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 8753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalShortArray: 8763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedShortArray: 8773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov_w(Operand(ecx, ebx, times_2, 0), eax); 8783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 8793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalIntArray: 8803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedIntArray: { 8813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // We also need to explicitly check for +/-Infinity. These are 8823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // converted to MIN_INT, but we need to be careful not to 8833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // confuse with legal uses of MIN_INT. 8843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Label not_infinity; 8853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // This test would apparently detect both NaN and Infinity, 8863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // but we've already checked for NaN using the FPU hardware 8873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // above. 8883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov_w(edi, FieldOperand(edx, HeapNumber::kValueOffset + 6)); 8893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ and_(edi, 0x7FF0); 8903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ cmp(edi, 0x7FF0); 8913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ j(not_equal, ¬_infinity); 8923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(eax, 0); 8933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(¬_infinity); 8943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(Operand(ecx, ebx, times_4, 0), eax); 8953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 8963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 8973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block default: 8983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block UNREACHABLE(); 8993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 9003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 9013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(eax, edx); // Return the original value. 9023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ret(0); 9033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&is_nan); 9053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ffree(); 9063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ fincstp(); 9073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block switch (array_type) { 9083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalByteArray: 9093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedByteArray: 9103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov_b(Operand(ecx, ebx, times_1, 0), 0); 9113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 9123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalShortArray: 9133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedShortArray: 9143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(eax, 0); 9153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov_w(Operand(ecx, ebx, times_2, 0), eax); 9163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 9173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalIntArray: 9183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case kExternalUnsignedIntArray: 9193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(Operand(ecx, ebx, times_4, 0), Immediate(0)); 9203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 9213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block default: 9223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block UNREACHABLE(); 9233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 9243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 9253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ mov(eax, edx); // Return the original value. 9263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ ret(0); 9273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 9283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Slow case: call runtime. 9303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ bind(&slow); 931402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateRuntimeSetProperty(masm); 9323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 9333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Defined in ic.cc. 936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* CallIC_Miss(Arguments args); 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { 939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 940e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 941e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 942e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 943e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 944e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label number, non_number, non_string, boolean, probe, miss; 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver of the function from the stack; 1 ~ return address. 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the stub cache. 952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Flags flags = 953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc); 954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, eax); 955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the stub cache probing failed, the receiver might be a value. 957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // For value objects, we use the map of the prototype objects for 958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the corresponding JSValue for the cache and that is what we need 959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to probe. 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for number. 962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(edx, Immediate(kSmiTagMask)); 963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &number, not_taken); 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ebx); 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &non_number, taken); 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&number); 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadGlobalFunctionPrototype( 968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm, Context::NUMBER_FUNCTION_INDEX, edx); 969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&probe); 970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for string. 972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&non_number); 973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(ebx, FIRST_NONSTRING_TYPE); 974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &non_string, taken); 975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadGlobalFunctionPrototype( 976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm, Context::STRING_FUNCTION_INDEX, edx); 977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&probe); 978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for boolean. 980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&non_string); 981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(edx, Factory::true_value()); 982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &boolean, not_taken); 983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(edx, Factory::false_value()); 984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss, taken); 985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&boolean); 986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCompiler::GenerateLoadGlobalFunctionPrototype( 987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm, Context::BOOLEAN_FUNCTION_INDEX, edx); 988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the stub cache for the value object. 990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&probe); 991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg); 992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cache miss: Jump to runtime. 994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 995e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke GenerateMiss(masm, argc); 996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GenerateNormalHelper(MacroAssembler* masm, 1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int argc, 1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_global_object, 1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 1003e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------- S t a t e ------------- 1004e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 1005e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- edx : receiver 1006e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 1007e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1008e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 1009e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 1010e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------------------------------- 1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1012e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Search dictionary - put result in register edi. 1013e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(edi, edx); 1014402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateDictionaryLoad(masm, miss, edx, ecx, eax, edi, ebx, CHECK_DICTIONARY); 1015e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1016e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the result is not a smi. 1017e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ test(edi, Immediate(kSmiTagMask)); 1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, miss, not_taken); 1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1020e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the value is a JavaScript function, fetching its map into eax. 1021e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax); 1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, miss, not_taken); 1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1024e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Patch the receiver on stack with the global proxy if necessary. 1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (is_global_object) { 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the function. 1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount actual(argc); 1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeFunction(edi, actual, JUMP_FUNCTION); 1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CallIC::GenerateNormal(MacroAssembler* masm, int argc) { 1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1038e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 1039e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 1040e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1041e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 1042e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss, global_object, non_global_object; 1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver of the function from the stack; 1 ~ return address. 1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(edx, Immediate(kSmiTagMask)); 1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &miss, not_taken); 1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver is a valid JS object. 1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); 1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(eax, FieldOperand(ebx, Map::kInstanceTypeOffset)); 1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, FIRST_JS_OBJECT_TYPE); 1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(below, &miss, not_taken); 1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If this assert fails, we have to check upper bound too. 1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for access to global object. 1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, JS_GLOBAL_OBJECT_TYPE); 1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &global_object); 1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, JS_BUILTINS_OBJECT_TYPE); 1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &non_global_object); 1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Accessing global object: Load and invoke. 1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&global_object); 1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the global object does not require access checks. 1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset)); 1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); 1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss, not_taken); 1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateNormalHelper(masm, argc, true, &miss); 1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Accessing non-global object: Check for access to global proxy. 1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label global_proxy, invoke; 1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&non_global_object); 1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, JS_GLOBAL_PROXY_TYPE); 1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &global_proxy, not_taken); 1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the non-global, non-global-proxy object does not 1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // require access checks. 1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset)); 1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); 1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss, not_taken); 1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&invoke); 1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateNormalHelper(masm, argc, false, &miss); 1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Global object proxy access: Check access rights. 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&global_proxy); 1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CheckAccessGlobalProxy(edx, eax, &miss); 1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&invoke); 1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cache miss: Jump to runtime. 1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 1096e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke GenerateMiss(masm, argc); 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1100e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid CallIC::GenerateMiss(MacroAssembler* masm, int argc) { 1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1102e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 1103e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 1104e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1105e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 1106e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver of the function from the stack; 1 ~ return address. 1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Enter an internal frame. 1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ EnterInternalFrame(); 1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push the receiver and the name of the function. 1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(edx); 1117e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(ecx); 1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call the entry. 1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CEntryStub stub(1); 1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, Immediate(2)); 1122e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(ebx, Immediate(ExternalReference(IC_Utility(kCallIC_Miss)))); 1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CallStub(&stub); 1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move result to edi and exit the internal frame. 1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edi, eax); 1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LeaveInternalFrame(); 1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the receiver is a global object of some sort. 1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label invoke, global; 1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); // receiver 1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(edx, Immediate(kSmiTagMask)); 1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &invoke, not_taken); 1134e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); 1135e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 1136e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(ebx, JS_GLOBAL_OBJECT_TYPE); 1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &global); 1138e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(ebx, JS_BUILTINS_OBJECT_TYPE); 1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &invoke); 1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack. 1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&global); 1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the function. 1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount actual(argc); 1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&invoke); 1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeFunction(edi, actual, JUMP_FUNCTION); 1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Defined in ic.cc. 1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* LoadIC_Miss(Arguments args); 1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateMegamorphic(MacroAssembler* masm) { 1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1158402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the stub cache. 1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, 1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NOT_IN_LOOP, 1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MONOMORPHIC); 1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCache::GenerateProbe(masm, flags, eax, ecx, ebx, edx); 1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cache miss: Jump to runtime. 1170402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateMiss(masm); 1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateNormal(MacroAssembler* masm) { 1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1176402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss, probe, global; 1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(eax, Immediate(kSmiTagMask)); 1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &miss, not_taken); 1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver is a valid JS object. 1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(edx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(edx, FIRST_JS_OBJECT_TYPE); 1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(less, &miss, not_taken); 1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If this assert fails, we have to check upper bound too. 1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for access to global object (unlikely). 1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(edx, JS_GLOBAL_PROXY_TYPE); 1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &global, not_taken); 1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for non-global object that requires access check. 1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset)); 1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); 1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &miss, not_taken); 1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Search the dictionary placing the result in eax. 1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&probe); 1206402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateDictionaryLoad(masm, 1207402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu &miss, 1208402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu eax, 1209402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ecx, 1210402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu edx, 1211402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu edi, 1212402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ebx, 1213402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu CHECK_DICTIONARY); 1214402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, edi); 1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Global object access: Check access rights. 1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&global); 1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CheckAccessGlobalProxy(eax, edx, &miss); 1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&probe); 1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cache miss: Restore receiver from stack and jump to runtime. 1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 1224402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateMiss(masm); 1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::GenerateMiss(MacroAssembler* masm) { 1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1230402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); 1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(eax); // receiver 1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); // name 1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); // return address 1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform tail call to the entry. 1241402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ TailCallRuntime(ExternalReference(IC_Utility(kLoadIC_Miss)), 2, 1); 1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// One byte opcode for test eax,0xXXXXXXXX. 1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const byte kTestEaxByte = 0xA9; 1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LoadIC::ClearInlinedVersion(Address address) { 1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reset the map check of the inlined inobject property load (if 1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // present) to guarantee failure by holding an invalid map (the null 1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // value). The offset can be patched to anything. 1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PatchInlinedLoad(address, Heap::null_value(), kMaxInt); 1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid KeyedLoadIC::ClearInlinedVersion(Address address) { 1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Insert null as the map to check for to make sure the map check fails 1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sending control flow to the IC instead of the inlined version. 1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PatchInlinedLoad(address, Heap::null_value()); 1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid KeyedStoreIC::ClearInlinedVersion(Address address) { 1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Insert null as the elements map to check for. This will make 1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sure that the elements fast-case map check fails so that control 1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // flows to the IC instead of the inlined version. 1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PatchInlinedStore(address, Heap::null_value()); 1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid KeyedStoreIC::RestoreInlinedVersion(Address address) { 1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore the fast-case elements map check so that the inlined 1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // version can be used again. 1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PatchInlinedStore(address, Heap::fixed_array_map()); 1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { 1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The address of the instruction following the call. 1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address test_instruction_address = 1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block address + Assembler::kCallTargetAddressOffset; 1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the instruction following the call is not a test eax, nothing 1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // was inlined. 1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*test_instruction_address != kTestEaxByte) return false; 1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address delta_address = test_instruction_address + 1; 1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The delta to the start of the map check instruction. 1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int delta = *reinterpret_cast<int*>(delta_address); 1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The map address is the last 4 bytes of the 7-byte 1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // operand-immediate compare instruction, so we add 3 to get the 1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // offset to the last 4 bytes. 1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address map_address = test_instruction_address + delta + 3; 1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *(reinterpret_cast<Object**>(map_address)) = map; 1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The offset is in the last 4 bytes of a six byte 1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // memory-to-register move instruction, so we add 2 to get the 1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // offset to the last 4 bytes. 1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address offset_address = 1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block test_instruction_address + delta + kOffsetToLoadInstruction + 2; 1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; 1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool PatchInlinedMapCheck(Address address, Object* map) { 1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address test_instruction_address = 1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block address + Assembler::kCallTargetAddressOffset; 1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The keyed load has a fast inlined case if the IC call instruction 1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is immediately followed by a test instruction. 1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*test_instruction_address != kTestEaxByte) return false; 1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fetch the offset from the test instruction to the map cmp 1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // instruction. This offset is stored in the last 4 bytes of the 5 1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // byte test instruction. 1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address delta_address = test_instruction_address + 1; 1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int delta = *reinterpret_cast<int*>(delta_address); 1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the map address. The map address is in the last 4 bytes 1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // of the 7-byte operand-immediate compare instruction, so we add 3 1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to the offset to get the map address. 1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address map_address = test_instruction_address + delta + 3; 1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the map check. 1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *(reinterpret_cast<Object**>(map_address)) = map; 1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool KeyedLoadIC::PatchInlinedLoad(Address address, Object* map) { 1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return PatchInlinedMapCheck(address, map); 1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool KeyedStoreIC::PatchInlinedStore(Address address, Object* map) { 1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return PatchInlinedMapCheck(address, map); 1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Defined in ic.cc. 1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadIC_Miss(Arguments args); 1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { 1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1345402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 1346402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1350402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(ebx); 1351402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(edx); // receiver 1352402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(eax); // name 1353402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(ebx); // return address 1354402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1355402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Perform tail call to the entry. 1356402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ TailCallRuntime(ExternalReference(IC_Utility(kKeyedLoadIC_Miss)), 2, 1); 1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1360402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { 1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1362402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 1363402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); 1368402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(edx); // receiver 1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(eax); // name 1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); // return address 1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform tail call to the entry. 1373402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ TailCallRuntime(ExternalReference(Runtime::kKeyedGetProperty), 2, 1); 1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StoreIC::GenerateMegamorphic(MacroAssembler* masm) { 1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 13814515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- edx : receiver 1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, 1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NOT_IN_LOOP, 1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MONOMORPHIC); 1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg); 1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cache miss: Jump to runtime. 13914515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke GenerateMiss(masm); 1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13954515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid StoreIC::GenerateMiss(MacroAssembler* masm) { 1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 13994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- edx : receiver 1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); 14044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(edx); 1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); 1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(eax); 1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); 1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform tail call to the entry. 14104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ TailCallRuntime(ExternalReference(IC_Utility(kStoreIC_Miss)), 3, 1); 1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Defined in ic.cc. 1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedStoreIC_Miss(Arguments args); 1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1417402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) { 1418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[4] : key 1422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[8] : receiver 1423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ecx); 1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(Operand(esp, 1 * kPointerSize)); 1427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(Operand(esp, 1 * kPointerSize)); 1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(eax); 1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); 1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to runtime routine. 1432402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3, 1); 1433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1436402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { 1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[4] : key 1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[8] : receiver 1442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1444402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(ecx); 1445402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(Operand(esp, 1 * kPointerSize)); 1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(Operand(esp, 1 * kPointerSize)); 1447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(eax); 1448402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(ecx); 1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to runtime routine. 1451402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ TailCallRuntime(ExternalReference(IC_Utility(kKeyedStoreIC_Miss)), 3, 1); 1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 1458