stub-cache-ia32.cc revision 592a9fc1d8ea420377a2e7efd0600e20b058be2b
18b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h" 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_IA32) 31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "ic-inl.h" 338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "codegen.h" 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "stub-cache.h" 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm) 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic void ProbeTable(Isolate* isolate, 4344f0eee88ff00398ff7f715fab053374d808c90dSteve Block MacroAssembler* masm, 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Flags flags, 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCache::Table table, 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register name, 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register offset, 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register extra) { 4944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference key_offset(isolate->stub_cache()->key_reference(table)); 5044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference value_offset(isolate->stub_cache()->value_reference(table)); 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (extra.is_valid()) { 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the code entry from the cache. 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(extra, Operand::StaticArray(offset, times_2, value_offset)); 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the key in the entry matches the name. 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(name, Operand::StaticArray(offset, times_2, key_offset)); 60257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the flags match what we're looking for. 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(offset, FieldOperand(extra, Code::kFlagsOffset)); 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(offset, ~Code::kFlagsNotUsedInLookup); 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(offset, flags); 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss); 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the first instruction in the code stub. 69592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ add(extra, Immediate(Code::kHeaderSize - kHeapObjectTag)); 70592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ jmp(extra); 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save the offset on the stack. 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(offset); 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the key in the entry matches the name. 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(name, Operand::StaticArray(offset, times_2, key_offset)); 79257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the code entry from the cache. 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(offset, Operand::StaticArray(offset, times_2, value_offset)); 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the flags match what we're looking for. 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(offset, FieldOperand(offset, Code::kFlagsOffset)); 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(offset, ~Code::kFlagsNotUsedInLookup); 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(offset, flags); 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss); 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore offset and re-load code entry from cache. 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(offset); 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(offset, Operand::StaticArray(offset, times_2, value_offset)); 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the first instruction in the code stub. 95592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ add(offset, Immediate(Code::kHeaderSize - kHeapObjectTag)); 96592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ jmp(offset); 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pop at miss. 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(offset); 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1058defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Helper function used to check that the dictionary doesn't contain 1068defd9ff6930b4e24729971a61cf7469daf119beSteve Block// the property. This function may return false negatives, so miss_label 1078defd9ff6930b4e24729971a61cf7469daf119beSteve Block// must always call a backup property check that is complete. 1088defd9ff6930b4e24729971a61cf7469daf119beSteve Block// This function is safe to call if the receiver has fast properties. 1098defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Name must be a symbol and receiver must be a heap object. 110592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochstatic void GenerateDictionaryNegativeLookup(MacroAssembler* masm, 111592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Label* miss_label, 112592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register receiver, 113592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name, 114592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register r0, 115592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register r1) { 1168defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(name->IsSymbol()); 11744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = masm->isolate()->counters(); 11844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->negative_lookups(), 1); 11944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->negative_lookups_miss(), 1); 1208defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1218defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); 1228defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1238defd9ff6930b4e24729971a61cf7469daf119beSteve Block const int kInterceptorOrAccessCheckNeededMask = 1248defd9ff6930b4e24729971a61cf7469daf119beSteve Block (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); 1253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1268defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Bail out if the receiver has a named interceptor or requires access checks. 1273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ test_b(FieldOperand(r0, Map::kBitFieldOffset), 1283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch kInterceptorOrAccessCheckNeededMask); 129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, miss_label); 1308defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Check that receiver is a JSObject. 1323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpInstanceType(r0, FIRST_SPEC_OBJECT_TYPE); 133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(below, miss_label); 1348defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1358defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Load properties array. 1368defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register properties = r0; 1378defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); 1388defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1398defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Check that the properties array is a dictionary. 1408defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ cmp(FieldOperand(properties, HeapObject::kMapOffset), 14144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Immediate(masm->isolate()->factory()->hash_table_map())); 1428defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(not_equal, miss_label); 1438defd9ff6930b4e24729971a61cf7469daf119beSteve Block 144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 145592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch StringDictionaryLookupStub::GenerateNegativeLookup(masm, 146592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch miss_label, 147592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch &done, 148592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch properties, 149592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch name, 150592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch r1); 1518defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ bind(&done); 15244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->negative_lookups_miss(), 1); 1538defd9ff6930b4e24729971a61cf7469daf119beSteve Block} 1548defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1558defd9ff6930b4e24729971a61cf7469daf119beSteve Block 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCache::GenerateProbe(MacroAssembler* masm, 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Flags flags, 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register name, 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 1613e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu Register extra, 1623e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu Register extra2) { 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 165592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Assert that code is valid. The shifting code relies on the entry size 166592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // being 8. 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(sizeof(Entry) == 8); 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 169592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Assert the flags do not name a specific type. 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(Code::ExtractTypeFromFlags(flags) == 0); 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 172592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Assert that there are no register conflicts. 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!scratch.is(receiver)); 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!scratch.is(name)); 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!extra.is(receiver)); 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!extra.is(name)); 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!extra.is(scratch)); 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 179592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Assert scratch and extra registers are valid, and extra2 is unused. 1803e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(!scratch.is(no_reg)); 1813e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(extra2.is(no_reg)); 1823e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 1843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(receiver, &miss); 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the map of the receiver and compute the hash. 187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ xor_(scratch, flags); 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the primary table. 193592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ProbeTable(isolate(), masm, flags, kPrimary, name, scratch, extra); 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Primary miss: Compute hash for secondary probe. 196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ xor_(scratch, flags); 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); 200592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ sub(scratch, name); 201592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ add(scratch, Immediate(flags)); 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(scratch, (kSecondaryTableSize - 1) << kHeapObjectTagSize); 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the secondary table. 205592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ProbeTable(isolate(), masm, flags, kSecondary, name, scratch, extra); 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cache miss: Fall-through and let caller handle the miss by 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // entering the runtime system. 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index, 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register prototype) { 21680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadGlobalFunction(index, prototype); 21780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadGlobalFunctionInitialMap(prototype, prototype); 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the prototype from the initial map. 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( 224592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch MacroAssembler* masm, 225592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch int index, 226592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register prototype, 227592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Label* miss) { 2280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Check we're still in the same context. 2290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ cmp(Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)), 23044f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm->isolate()->global()); 2310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ j(not_equal, miss); 2327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Get the global function with the given index. 233592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSFunction> function( 234592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch JSFunction::cast(masm->isolate()->global_context()->get(index))); 2357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Load its initial map. The global functions all have initial maps. 2367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Set(prototype, Immediate(Handle<Map>(function->initial_map()))); 2377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Load the prototype from the initial map. 2387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); 2397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 2407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss_label) { 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 2473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(receiver, miss_label); 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is a JS array. 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); 251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, miss_label); 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load length directly from the JS array. 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset)); 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate code to check if an object is a string. If the object is 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// a string, the map's instance type is left in the scratch register. 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GenerateStringCheck(MacroAssembler* masm, 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* smi, 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* non_string_object) { 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object isn't a smi. 2673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(receiver, smi); 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is a string. 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 27269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kNotStringTag != 0); 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(scratch, Immediate(kNotStringTag)); 274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, non_string_object); 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 280402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register scratch1, 281402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register scratch2, 2821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* miss, 2831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool support_wrappers) { 284402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label check_wrapper; 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the object is a string leaving the instance type in the 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch register. 2881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block GenerateStringCheck(masm, receiver, scratch1, miss, 2891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block support_wrappers ? &check_wrapper : miss); 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 291d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load length from the string and convert to a smi. 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, FieldOperand(receiver, String::kLengthOffset)); 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (support_wrappers) { 2961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check if the object is a JSValue wrapper. 2971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&check_wrapper); 2981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmp(scratch1, JS_VALUE_TYPE); 299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, miss); 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check if the wrapped value is a string and load the length 3021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // directly if it is. 3031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset)); 3041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block GenerateStringCheck(masm, scratch2, scratch1, miss, miss); 3051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(eax, FieldOperand(scratch2, String::kLengthOffset)); 3061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 3071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss_label) { 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); 317592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(eax, scratch1); 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Load a fast property out of a holder object (src). In-object properties 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// are loaded directly otherwise the property is loaded from the properties 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// fixed array. 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, 326592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register dst, 327592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register src, 328592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder, 329592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch int index) { 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust for the number of properties stored in the holder. 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block index -= holder->map()->inobject_properties(); 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (index < 0) { 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the property straight out of the holder. 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = holder->map()->instance_size() + (index * kPointerSize); 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(dst, FieldOperand(src, offset)); 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the offset into the properties array. 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = index * kPointerSize + FixedArray::kHeaderSize; 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(dst, FieldOperand(dst, offset)); 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 345402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescustatic void PushInterceptorArguments(MacroAssembler* masm, 346402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register receiver, 347402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register holder, 348402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register name, 349592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder_obj) { 350402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(name); 351592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); 352592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); 3536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch = name; 354592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(scratch, Immediate(interceptor)); 3556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(scratch); 356402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(receiver); 3576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(holder); 3586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(FieldOperand(scratch, InterceptorInfo::kDataOffset)); 359402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 360402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 361402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 362592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochstatic void CompileCallLoadPropertyWithInterceptor( 363592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch MacroAssembler* masm, 364592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register receiver, 365592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register holder, 366592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register name, 367592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder_obj) { 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PushInterceptorArguments(masm, receiver, holder, name, holder_obj); 369402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CallExternalReference( 37044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), 37144f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm->isolate()), 37244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 5); 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 37690bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner// Number of pointers to be reserved on stack for fast API call. 37790bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brennerstatic const int kFastApiCallArguments = 3; 37890bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner 37990bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner 3808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang// Reserves space for the extra arguments to API function in the 381402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// caller's frame. 382402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// 383402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// These arguments are set by CheckPrototypes and GenerateFastApiCall. 384402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescustatic void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { 385402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------- S t a t e ------------- 386402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- esp[0] : return address 387402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- esp[4] : last argument in the internal frame of the caller 388402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------------------------------- 389402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(scratch); 39090bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner for (int i = 0; i < kFastApiCallArguments; i++) { 39190bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner __ push(Immediate(Smi::FromInt(0))); 39290bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner } 393402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(scratch); 394402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 395402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 396402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 397402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// Undoes the effects of ReserveSpaceForFastApiCall. 398402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescustatic void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { 399402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------- S t a t e ------------- 40090bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner // -- esp[0] : return address. 40190bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner // -- esp[4] : last fast api call extra argument. 402402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- ... 40390bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner // -- esp[kFastApiCallArguments * 4] : first fast api call extra argument. 40490bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner // -- esp[kFastApiCallArguments * 4 + 4] : last argument in the internal 40590bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner // frame. 406402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------------------------------- 407402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(scratch); 408592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ add(esp, Immediate(kPointerSize * kFastApiCallArguments)); 409402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(scratch); 410402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 411402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 412402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 4138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang// Generates call to API function. 414592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochstatic void GenerateFastApiCall(MacroAssembler* masm, 415592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch const CallOptimization& optimization, 416592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch int argc) { 417402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------- S t a t e ------------- 418402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- esp[0] : return address 419402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- esp[4] : object passing the type check 420402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // (last fast api call extra argument, 421402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // set by CheckPrototypes) 42290bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner // -- esp[8] : api function 423402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // (first fast api call extra argument) 42490bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner // -- esp[12] : api call data 42590bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner // -- esp[16] : last argument 426402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- ... 42790bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner // -- esp[(argc + 3) * 4] : first argument 42890bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner // -- esp[(argc + 4) * 4] : receiver 429402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------------------------------- 430402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Get the function and setup the context. 431592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSFunction> function = optimization.constant_function(); 432592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(edi, Immediate(function)); 433402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 434402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 4358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Pass the additional arguments. 43690bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner __ mov(Operand(esp, 2 * kPointerSize), edi); 437592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 438592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Object> call_data(api_call_info->data()); 439592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (masm->isolate()->heap()->InNewSpace(*call_data)) { 440592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(ecx, api_call_info); 441402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset)); 44290bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner __ mov(Operand(esp, 3 * kPointerSize), ebx); 443402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 444592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(Operand(esp, 3 * kPointerSize), Immediate(call_data)); 445402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 446402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 4478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Prepare arguments. 44890bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner __ lea(eax, Operand(esp, 3 * kPointerSize)); 449402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 4508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const int kApiArgc = 1; // API function gets reference to the v8::Arguments. 45190bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner 4528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Allocate the v8::Arguments structure in the arguments' space since 4538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // it's not controlled by GC. 4548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const int kApiStackSpace = 4; 4558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 4563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ PrepareCallApiFunction(kApiArgc + kApiStackSpace); 4578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 4588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(ApiParameterOperand(1), eax); // v8::Arguments::implicit_args_. 459592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ add(eax, Immediate(argc * kPointerSize)); 4608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(ApiParameterOperand(2), eax); // v8::Arguments::values_. 4618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Set(ApiParameterOperand(3), Immediate(argc)); // v8::Arguments::length_. 4628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // v8::Arguments::is_construct_call_. 4638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Set(ApiParameterOperand(4), Immediate(0)); 4648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 4658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // v8::InvocationCallback's argument. 4668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ lea(eax, ApiParameterOperand(1)); 4678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(ApiParameterOperand(0), eax); 46890bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner 469592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Function address is a foreign pointer outside V8's heap. 470592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Address function_address = v8::ToCData<Address>(api_call_info->callback()); 471592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ CallApiFunctionAndReturn(function_address, 472592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch argc + kFastApiCallArguments + 1); 473402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 474402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 475402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CallInterceptorCompiler BASE_EMBEDDED { 477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 478402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu CallInterceptorCompiler(StubCompiler* stub_compiler, 479402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu const ParameterCount& arguments, 480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register name, 481592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Code::ExtraICState extra_state) 482402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu : stub_compiler_(stub_compiler), 483402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu arguments_(arguments), 484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch name_(name), 485592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch extra_state_(extra_state) {} 486592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 487592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch void Compile(MacroAssembler* masm, 488592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> object, 489592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder, 490592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name, 491592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch LookupResult* lookup, 492592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register receiver, 493592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register scratch1, 494592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register scratch2, 495592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register scratch3, 496592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Label* miss) { 497402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(holder->HasNamedInterceptor()); 498402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); 499402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 500402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Check that the receiver isn't a smi. 5013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(receiver, miss); 502402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 503402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu CallOptimization optimization(lookup); 5046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (optimization.is_constant_call()) { 505592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3, 506592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch holder, lookup, name, optimization, miss); 507402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 508592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3, 509592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch name, holder, miss); 510402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 511402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 513402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu private: 514592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch void CompileCacheable(MacroAssembler* masm, 515592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> object, 516592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register receiver, 517592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register scratch1, 518592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register scratch2, 519592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register scratch3, 520592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> interceptor_holder, 521592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch LookupResult* lookup, 522592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name, 523592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch const CallOptimization& optimization, 524592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Label* miss_label) { 525402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(optimization.is_constant_call()); 526402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(!lookup->holder()->IsGlobalObject()); 527402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 528402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int depth1 = kInvalidProtoDepth; 529402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int depth2 = kInvalidProtoDepth; 530402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu bool can_do_fast_api_call = false; 531402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (optimization.is_simple_api_call() && 532402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu !lookup->holder()->IsGlobalObject()) { 533592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch depth1 = optimization.GetPrototypeDepthOfExpectedType( 534592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch object, interceptor_holder); 535402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (depth1 == kInvalidProtoDepth) { 536592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch depth2 = optimization.GetPrototypeDepthOfExpectedType( 537592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch interceptor_holder, Handle<JSObject>(lookup->holder())); 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 539592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch can_do_fast_api_call = 540592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth; 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 54344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = masm->isolate()->counters(); 54444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_const_interceptor(), 1); 545402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 546402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (can_do_fast_api_call) { 54744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1); 548402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ReserveSpaceForFastApiCall(masm, scratch1); 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check that the maps from receiver to interceptor's holder 552f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // haven't changed and thus we can invoke interceptor. 553402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label miss_cleanup; 554402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; 555402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register holder = 556592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, 557592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch scratch1, scratch2, scratch3, 558592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch name, depth1, miss); 559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invoke an interceptor and if it provides a value, 561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // branch to |regular_invoke|. 562402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label regular_invoke; 563f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke LoadWithInterceptor(masm, receiver, holder, interceptor_holder, 564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ®ular_invoke); 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Interceptor returned nothing for this property. Try to use cached 567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // constant function. 568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 569f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check that the maps from interceptor's holder to constant function's 570f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // holder haven't changed and thus we can use cached constant function. 571592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (*interceptor_holder != lookup->holder()) { 5727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch stub_compiler_->CheckPrototypes(interceptor_holder, receiver, 573592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject>(lookup->holder()), 574592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch scratch1, scratch2, scratch3, 575592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch name, depth2, miss); 5767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 5777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // CheckPrototypes has a side effect of fetching a 'holder' 5787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // for API (object which is instanceof for the signature). It's 5797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // safe to omit it here, as if present, it should be fetched 5807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // by the previous CheckPrototypes. 5817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(depth2 == kInvalidProtoDepth); 5827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 584f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invoke function. 585402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (can_do_fast_api_call) { 586592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateFastApiCall(masm, optimization, arguments_.immediate()); 587402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 588592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 591402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ InvokeFunction(optimization.constant_function(), arguments_, 592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch JUMP_FUNCTION, NullCallWrapper(), call_kind); 593402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Deferred code for fast API call case---clean preallocated space. 596402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (can_do_fast_api_call) { 597402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ bind(&miss_cleanup); 598402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu FreeSpaceForFastApiCall(masm, scratch1); 599402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ jmp(miss_label); 600402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 602f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invoke a regular function. 603402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ bind(®ular_invoke); 604402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (can_do_fast_api_call) { 605402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu FreeSpaceForFastApiCall(masm, scratch1); 606402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CompileRegular(MacroAssembler* masm, 610592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> object, 611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 612402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register scratch1, 613402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register scratch2, 6143bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 615592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name, 616592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> interceptor_holder, 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss_label) { 618402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register holder = 619f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, 620592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch scratch1, scratch2, scratch3, 621592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch name, miss_label); 622402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 623592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 624e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save the name_ register across the call. 625e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(name_); 626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 627592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder); 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 629402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CallExternalReference( 63044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), 63144f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm->isolate()), 63244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 5); 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 634e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Restore the name_ register. 635e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(name_); 636592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 637592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Leave the internal frame. 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 640402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void LoadWithInterceptor(MacroAssembler* masm, 641402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register receiver, 642402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register holder, 643592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder_obj, 644402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label* interceptor_succeeded) { 645592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch { 646592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 647592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(holder); // Save the holder. 648592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(name_); // Save the name. 649592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 650592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CompileCallLoadPropertyWithInterceptor(masm, 651592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch receiver, 652592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch holder, 653592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch name_, 654592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch holder_obj); 655592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 656592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ pop(name_); // Restore the name. 657592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ pop(receiver); // Restore the holder. 658592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Leave the internal frame. 659592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 660402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 66144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(eax, masm->isolate()->factory()->no_interceptor_result_sentinel()); 662402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ j(not_equal, interceptor_succeeded); 663402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 664402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 665402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu StubCompiler* stub_compiler_; 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& arguments_; 667e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register name_; 668592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Code::ExtraICState extra_state_; 669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { 673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); 674592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Code> code = (kind == Code::LOAD_IC) 675592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ? masm->isolate()->builtins()->LoadIC_Miss() 676592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch : masm->isolate()->builtins()->KeyedLoadIC_Miss(); 677592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ jmp(code, RelocInfo::CODE_TARGET); 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) { 682592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Code> code = 683592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 684592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ jmp(code, RelocInfo::CODE_TARGET); 685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 688402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// Both name_reg and receiver_reg are preserved on jumps to miss_label, 689402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// but may be destroyed if store is successful. 690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateStoreField(MacroAssembler* masm, 691592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> object, 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index, 693592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Map> transition, 694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver_reg, 695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register name_reg, 696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss_label) { 698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object isn't a smi. 6993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(receiver_reg, miss_label); 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the object hasn't changed. 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset), 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(Handle<Map>(object->map()))); 704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, miss_label); 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform global security token check if needed. 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsJSGlobalProxy()) { 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); 709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stub never generated for non-global objects that require access 712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks. 713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform map transition for the receiver if necessary. 716592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) { 717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The properties must be extended before we can store the value. 718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We jump to a runtime call that extends the properties array. 719402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(scratch); // Return address. 720402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(receiver_reg); 721592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(Immediate(transition)); 722402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(eax); 723402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(scratch); 7246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference( 72544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), 72644f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm->isolate()), 72744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3, 72844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1); 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 732592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (!transition.is_null()) { 733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update the map of the object; no write barrier updating is 734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // needed because the map is never in new space. 735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset), 736592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Immediate(transition)); 737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust for the number of properties stored in the object. Even in the 740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // face of a transition we can use the old map here because the size of the 741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object and the number of in-object properties is not going to change. 742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block index -= object->map()->inobject_properties(); 743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (index < 0) { 745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the property straight into the object. 746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = object->map()->instance_size() + (index * kPointerSize); 747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(FieldOperand(receiver_reg, offset), eax); 748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update the write barrier for the array address. 750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pass the value being stored in the now unused name_reg. 751592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(name_reg, eax); 752592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ RecordWriteField(receiver_reg, 753592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch offset, 754592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch name_reg, 755592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch scratch, 756592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch kDontSaveFPRegs); 757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Write to the properties array. 759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = index * kPointerSize + FixedArray::kHeaderSize; 760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the properties array (optimistically). 761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); 762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(FieldOperand(scratch, offset), eax); 763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update the write barrier for the array address. 765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pass the value being stored in the now unused name_reg. 766592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(name_reg, eax); 767592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ RecordWriteField(scratch, 768592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch offset, 769592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch name_reg, 770592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch receiver_reg, 771592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch kDontSaveFPRegs); 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the value (register eax). 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Generate code to check that a global property cell is empty. Create 7806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// the property cell at compilation time if no cell exists for the 7816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// property. 782592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochstatic void GenerateCheckPropertyCell(MacroAssembler* masm, 783592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<GlobalObject> global, 784592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name, 785592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register scratch, 786592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Label* miss) { 787592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSGlobalPropertyCell> cell = 788592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GlobalObject::EnsurePropertyCell(global, name); 7896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(cell->value()->IsTheHole()); 790592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Oddball> the_hole = masm->isolate()->factory()->the_hole_value(); 791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (Serializer::enabled()) { 792592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(scratch, Immediate(cell)); 793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), 794592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Immediate(the_hole)); 795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 796592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(Operand::Cell(cell), Immediate(the_hole)); 797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, miss); 7996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 8006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8028defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Calls GenerateCheckPropertyCell for each global object in the prototype chain 8038defd9ff6930b4e24729971a61cf7469daf119beSteve Block// from object to (but not including) holder. 804592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochstatic void GenerateCheckPropertyCells(MacroAssembler* masm, 805592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> object, 806592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder, 807592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name, 808592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register scratch, 809592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Label* miss) { 810592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> current = object; 811592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch while (!current.is_identical_to(holder)) { 8128defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (current->IsGlobalObject()) { 813592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateCheckPropertyCell(masm, 814592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<GlobalObject>::cast(current), 815592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch name, 816592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch scratch, 817592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch miss); 8188defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 819592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); 8208defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 8218defd9ff6930b4e24729971a61cf7469daf119beSteve Block} 8228defd9ff6930b4e24729971a61cf7469daf119beSteve Block 823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm()) 825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 827592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochRegister StubCompiler::CheckPrototypes(Handle<JSObject> object, 828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register object_reg, 829592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder, 830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register holder_reg, 8313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch1, 8323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch2, 833592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name, 8348defd9ff6930b4e24729971a61cf7469daf119beSteve Block int save_at_depth, 8353bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* miss) { 8368defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Make sure there's no overlap between holder and object registers. 8373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 8383bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) 8393bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch && !scratch2.is(scratch1)); 84044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 8418defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Keep track of the current object in register reg. 8428defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register reg = object_reg; 843592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> current = object; 8448defd9ff6930b4e24729971a61cf7469daf119beSteve Block int depth = 0; 8458defd9ff6930b4e24729971a61cf7469daf119beSteve Block 8468defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (save_at_depth == depth) { 8478defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(Operand(esp, kPointerSize), reg); 8488defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8508defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Traverse the prototype chain and check the maps in the prototype chain for 8518defd9ff6930b4e24729971a61cf7469daf119beSteve Block // fast and global objects or do negative lookup for normal objects. 852592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch while (!current.is_identical_to(holder)) { 853592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ++depth; 8548defd9ff6930b4e24729971a61cf7469daf119beSteve Block 8558defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Only global objects and objects that do not require access 8568defd9ff6930b4e24729971a61cf7469daf119beSteve Block // checks are allowed in stubs. 8578defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); 8588defd9ff6930b4e24729971a61cf7469daf119beSteve Block 859592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> prototype(JSObject::cast(current->GetPrototype())); 8608defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (!current->HasFastProperties() && 8618defd9ff6930b4e24729971a61cf7469daf119beSteve Block !current->IsJSGlobalObject() && 8628defd9ff6930b4e24729971a61cf7469daf119beSteve Block !current->IsJSGlobalProxy()) { 8638defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (!name->IsSymbol()) { 864592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch name = factory()->LookupSymbol(name); 8658defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 866592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT(current->property_dictionary()->FindEntry(*name) == 8678defd9ff6930b4e24729971a61cf7469daf119beSteve Block StringDictionary::kNotFound); 8688defd9ff6930b4e24729971a61cf7469daf119beSteve Block 869592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateDictionaryNegativeLookup(masm(), miss, reg, name, 870592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch scratch1, scratch2); 871257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 8723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); 873592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch reg = holder_reg; // From now on the object will be in holder_reg. 8743bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); 875592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } else { 876592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch bool in_new_space = heap()->InNewSpace(*prototype); 877592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Map> current_map(current->map()); 878592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (in_new_space) { 879592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Save the map in scratch1 for later. 8803bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); 881592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(scratch1, Immediate(current_map)); 882592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } else { 883592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(FieldOperand(reg, HeapObject::kMapOffset), 884592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Immediate(current_map)); 8858defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 8868defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Branch on the result of the map check. 887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, miss); 888592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Check access rights to the global object. This has to happen after 889592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // the map check so that we know that the object is actually a global 890592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // object. 8918defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (current->IsJSGlobalProxy()) { 892592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ CheckAccessGlobalProxy(reg, scratch2, miss); 893592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 894592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch reg = holder_reg; // From now on the object will be in holder_reg. 895592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 896592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (in_new_space) { 897592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // The prototype is in new space; we cannot store a reference to it 898592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // in the code. Load it from the map. 899592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); 900592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } else { 901592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // The prototype is in old space; load it directly. 902592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(reg, prototype); 903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 9058defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9068defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (save_at_depth == depth) { 9078defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(Operand(esp, kPointerSize), reg); 9088defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 9098defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9108defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Go to the next object in the prototype chain. 9118defd9ff6930b4e24729971a61cf7469daf119beSteve Block current = prototype; 912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 913592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT(current.is_identical_to(holder)); 9148defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9158defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Log the check depth. 91644f0eee88ff00398ff7f715fab053374d808c90dSteve Block LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); 9178defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9188defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Check the holder map. 9198defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ cmp(FieldOperand(reg, HeapObject::kMapOffset), 9208defd9ff6930b4e24729971a61cf7469daf119beSteve Block Immediate(Handle<Map>(holder->map()))); 921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, miss); 9228defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9238defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Perform security check for access to the global object. 9248defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); 9258defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (holder->IsJSGlobalProxy()) { 9263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ CheckAccessGlobalProxy(reg, scratch1, miss); 927592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 928592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 929592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // If we've skipped any global objects, it's not enough to verify that 930592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // their maps haven't changed. We also need to check that the property 931592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // cell for the property is still empty. 932592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); 933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 934402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Return the register containing the holder. 9358defd9ff6930b4e24729971a61cf7469daf119beSteve Block return reg; 936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 939592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid StubCompiler::GenerateLoadField(Handle<JSObject> object, 940592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder, 941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 9443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index, 946592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name, 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 9493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(receiver, miss); 950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the prototype chain. 952592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register reg = CheckPrototypes( 953592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch object, receiver, holder, scratch1, scratch2, scratch3, name, miss); 954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the value from the properties. 956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateFastPropertyLoad(masm(), eax, reg, holder, index); 957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 961592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid StubCompiler::GenerateLoadCallback(Handle<JSObject> object, 962592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder, 963592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register receiver, 964592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register name_reg, 965592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register scratch1, 966592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register scratch2, 967592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register scratch3, 968592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<AccessorInfo> callback, 969592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name, 970592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Label* miss) { 971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 9723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(receiver, miss); 973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 975592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register reg = CheckPrototypes(object, receiver, holder, scratch1, 976592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch scratch2, scratch3, name, miss); 977d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 9788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Insert additional parameters into the stack frame above return address. 9798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ASSERT(!scratch3.is(reg)); 9808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ pop(scratch3); // Get return address to place it below. 9818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(receiver); // receiver 983592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(scratch2, esp); 9848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ASSERT(!scratch2.is(reg)); 985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(reg); // holder 9869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Push data from AccessorInfo. 987592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (isolate()->heap()->InNewSpace(callback->data())) { 988592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(scratch1, Immediate(callback)); 9898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset)); 9909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } else { 991592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(Immediate(Handle<Object>(callback->data()))); 9929dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 9938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 994d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Save a pointer to where we pushed the arguments pointer. 9956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // This will be passed as the const AccessorInfo& to the C++ callback. 9968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(scratch2); 9978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 9988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(name_reg); // name 9998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(ebx, esp); // esp points to reference to name (handler). 10008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 10018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(scratch3); // Restore return address. 1002d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 10038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // 3 elements array for v8::Agruments::values_, handler for name and pointer 10048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // to the values (it considered as smi in GC). 10058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const int kStackSpace = 5; 10068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const int kApiArgc = 2; 10078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 10083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ PrepareCallApiFunction(kApiArgc); 10098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(ApiParameterOperand(0), ebx); // name. 1010592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ add(ebx, Immediate(kPointerSize)); 10118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(ApiParameterOperand(1), ebx); // arguments pointer. 10128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1013e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emitting a stub call may try to allocate (if the code is not 1014e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // already generated). Do not allow the assembler to perform a 1015e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // garbage collection but instead return the allocation failure 1016e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // object. 1017592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Address getter_address = v8::ToCData<Address>(callback->getter()); 1018592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ CallApiFunctionAndReturn(getter_address, kStackSpace); 1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1022592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid StubCompiler::GenerateLoadConstant(Handle<JSObject> object, 1023592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder, 1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 10273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 1028592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Object> value, 1029592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name, 1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 10323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(receiver, miss); 1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 1035592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CheckPrototypes( 1036592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch object, receiver, holder, scratch1, scratch2, scratch3, name, miss); 1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the constant value. 1039592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(eax, value); 1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1044592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object, 1045592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> interceptor_holder, 1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupResult* lookup, 1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register name_reg, 1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 10513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 1052592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name, 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 10547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(interceptor_holder->HasNamedInterceptor()); 10557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); 10567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 10577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the receiver isn't a smi. 10583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(receiver, miss); 10597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 10607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // So far the most popular follow ups for interceptor loads are FIELD 10617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // and CALLBACKS, so inline only them, other cases may be added 10627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // later. 10637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch bool compile_followup_inline = false; 10647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (lookup->IsProperty() && lookup->IsCacheable()) { 10657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (lookup->type() == FIELD) { 10667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch compile_followup_inline = true; 10677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else if (lookup->type() == CALLBACKS && 1068592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch lookup->GetCallbackObject()->IsAccessorInfo()) { 1069592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch compile_followup_inline = 1070592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL; 10717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 10727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 10737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 10747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (compile_followup_inline) { 10757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Compile the interceptor call, followed by inline code to load the 10767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // property from further up the prototype chain if the call fails. 10777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps haven't changed. 10787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, 10793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch1, scratch2, scratch3, 10803bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch name, miss); 10817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1)); 10827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 10837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Save necessary data before invoking an interceptor. 10847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Requires a frame to make GC aware of pushed pointers. 1085592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch { 1086592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch FrameScope frame_scope(masm(), StackFrame::INTERNAL); 10877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1088592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { 1089592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // CALLBACKS case needs a receiver to be passed into C++ callback. 1090592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(receiver); 1091592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 1092592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(holder_reg); 1093592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(name_reg); 10947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1095592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Invoke an interceptor. Note: map checks from receiver to 1096592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // interceptor's holder has been compiled before (see a caller 1097592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // of this method.) 1098592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CompileCallLoadPropertyWithInterceptor(masm(), 1099592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch receiver, 1100592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch holder_reg, 1101592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch name_reg, 1102592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch interceptor_holder); 1103592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1104592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Check if interceptor provided a value for property. If it's 1105592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // the case, return immediately. 1106592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Label interceptor_failed; 1107592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(eax, factory()->no_interceptor_result_sentinel()); 1108592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ j(equal, &interceptor_failed); 1109592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch frame_scope.GenerateLeaveFrame(); 1110592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ret(0); 11117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1112592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(&interceptor_failed); 1113592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ pop(name_reg); 1114592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ pop(holder_reg); 1115592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { 1116592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ pop(receiver); 1117592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 1118592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1119592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Leave the internal frame. 1120592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 11217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps from interceptor's holder to lookup's holder 11237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // haven't changed. And load lookup's holder into holder_reg. 1124592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (*interceptor_holder != lookup->holder()) { 11257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch holder_reg = CheckPrototypes(interceptor_holder, 11267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch holder_reg, 1127592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject>(lookup->holder()), 11287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch1, 11297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch2, 11303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch3, 11317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch name, 11327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch miss); 11337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 11347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (lookup->type() == FIELD) { 11367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // We found FIELD property in prototype chain of interceptor's holder. 11377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Retrieve a field from field's holder. 11387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateFastPropertyLoad(masm(), eax, holder_reg, 1139592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject>(lookup->holder()), 1140592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch lookup->GetFieldIndex()); 11417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ ret(0); 11427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 11437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // We found CALLBACKS property in prototype chain of interceptor's 11447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // holder. 11457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(lookup->type() == CALLBACKS); 1146592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<AccessorInfo> callback( 1147592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch AccessorInfo::cast(lookup->GetCallbackObject())); 11487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(callback->getter() != NULL); 11497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Tail call to runtime. 11517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Important invariant in CALLBACKS case: the code above must be 11527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // structured to never clobber |receiver| register. 11537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(scratch2); // return address 11547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(receiver); 11557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(holder_reg); 1156592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(holder_reg, Immediate(callback)); 11577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset)); 11588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(holder_reg); 11597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(name_reg); 11607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(scratch2); // restore return address 11617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ExternalReference ref = 116344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kLoadCallbackProperty), 116444f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm()->isolate()); 11657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ TailCallExternalReference(ref, 5, 1); 11667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 11677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { // !compile_followup_inline 11687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Call the runtime system to load the interceptor. 11697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps haven't changed. 11707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register holder_reg = 11717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch CheckPrototypes(object, receiver, interceptor_holder, 11723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch1, scratch2, scratch3, name, miss); 11737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(scratch2); // save old return address 11747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch PushInterceptorArguments(masm(), receiver, holder_reg, 11757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch name_reg, interceptor_holder); 11767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(scratch2); // restore old return address 11777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 117844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference ref = 117944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), 118044f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()); 11817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ TailCallExternalReference(ref, 5, 1); 11827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1186592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { 11877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (kind_ == Code::KEYED_CALL_IC) { 1188592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(ecx, Immediate(name)); 1189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, miss); 11907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 11917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 11927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1194592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object, 1195592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder, 1196592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name, 119759151504615d929945dc59db37bf1166937748c6Steve Block Label* miss) { 119859151504615d929945dc59db37bf1166937748c6Steve Block ASSERT(holder->IsGlobalObject()); 119959151504615d929945dc59db37bf1166937748c6Steve Block 120059151504615d929945dc59db37bf1166937748c6Steve Block // Get the number of arguments. 120159151504615d929945dc59db37bf1166937748c6Steve Block const int argc = arguments().immediate(); 120259151504615d929945dc59db37bf1166937748c6Steve Block 120359151504615d929945dc59db37bf1166937748c6Steve Block // Get the receiver from the stack. 120459151504615d929945dc59db37bf1166937748c6Steve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 120559151504615d929945dc59db37bf1166937748c6Steve Block 120659151504615d929945dc59db37bf1166937748c6Steve Block // If the object is the holder then we know that it's a global 120759151504615d929945dc59db37bf1166937748c6Steve Block // object which can only happen for contextual calls. In this case, 120859151504615d929945dc59db37bf1166937748c6Steve Block // the receiver cannot be a smi. 1209592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (!object.is_identical_to(holder)) { 12103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, miss); 121159151504615d929945dc59db37bf1166937748c6Steve Block } 121259151504615d929945dc59db37bf1166937748c6Steve Block 121359151504615d929945dc59db37bf1166937748c6Steve Block // Check that the maps haven't changed. 121459151504615d929945dc59db37bf1166937748c6Steve Block CheckPrototypes(object, edx, holder, ebx, eax, edi, name, miss); 121559151504615d929945dc59db37bf1166937748c6Steve Block} 121659151504615d929945dc59db37bf1166937748c6Steve Block 121759151504615d929945dc59db37bf1166937748c6Steve Block 1218592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid CallStubCompiler::GenerateLoadFunctionFromCell( 1219592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSGlobalPropertyCell> cell, 1220592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSFunction> function, 1221592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Label* miss) { 122259151504615d929945dc59db37bf1166937748c6Steve Block // Get the value from the cell. 1223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (Serializer::enabled()) { 1224592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(edi, Immediate(cell)); 1225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); 1226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1227592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(edi, Operand::Cell(cell)); 1228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 122959151504615d929945dc59db37bf1166937748c6Steve Block 123059151504615d929945dc59db37bf1166937748c6Steve Block // Check that the cell contains the same function. 1231592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (isolate()->heap()->InNewSpace(*function)) { 123259151504615d929945dc59db37bf1166937748c6Steve Block // We can't embed a pointer to a function in new space so we have 123359151504615d929945dc59db37bf1166937748c6Steve Block // to verify that the shared function info is unchanged. This has 123459151504615d929945dc59db37bf1166937748c6Steve Block // the nice side effect that multiple closures based on the same 123559151504615d929945dc59db37bf1166937748c6Steve Block // function can all use this call IC. Before we load through the 123659151504615d929945dc59db37bf1166937748c6Steve Block // function, we have to verify that it still is a function. 12373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edi, miss); 123859151504615d929945dc59db37bf1166937748c6Steve Block __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); 1239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, miss); 124059151504615d929945dc59db37bf1166937748c6Steve Block 124159151504615d929945dc59db37bf1166937748c6Steve Block // Check the shared function info. Make sure it hasn't changed. 124259151504615d929945dc59db37bf1166937748c6Steve Block __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), 124359151504615d929945dc59db37bf1166937748c6Steve Block Immediate(Handle<SharedFunctionInfo>(function->shared()))); 124459151504615d929945dc59db37bf1166937748c6Steve Block } else { 1245592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(edi, Immediate(function)); 124659151504615d929945dc59db37bf1166937748c6Steve Block } 1247592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ j(not_equal, miss); 124859151504615d929945dc59db37bf1166937748c6Steve Block} 124959151504615d929945dc59db37bf1166937748c6Steve Block 125059151504615d929945dc59db37bf1166937748c6Steve Block 1251592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid CallStubCompiler::GenerateMissBranch() { 1252592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Code> code = 125344f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), 1254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch kind_, 1255592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch extra_state_); 1256592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ jmp(code, RelocInfo::CODE_TARGET); 12577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 12587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1260592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, 1261592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder, 1262592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch int index, 1263592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name) { 1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1265e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 1266e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 1267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 1269e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateNameCheck(name, &miss); 12747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver from the stack. 1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 12803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &miss); 1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do the right check and compute the holder register. 12833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register reg = CheckPrototypes(object, edx, holder, ebx, eax, edi, 12843bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch name, &miss); 1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateFastPropertyLoad(masm(), edi, reg, holder, index); 1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the function really is a function. 12893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edi, &miss); 1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); 1291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack with the global proxy if 1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // necessary. 1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsGlobalObject()) { 1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the function. 1301592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 1302257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 1303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 1304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, 1305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), call_kind); 1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 1309592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateMissBranch(); 1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(FIELD, name); 1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1316592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> CallStubCompiler::CompileArrayPushCall( 1317592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Object> object, 1318592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder, 1319592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSGlobalPropertyCell> cell, 1320592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSFunction> function, 1321592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name) { 13226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 13236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : name 13246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[0] : return address 13256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[(argc - n) * 4] : arg[n] (zero-based) 13266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ... 13276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[(argc + 1) * 4] : receiver 13286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 13296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // If object is not an array, bail out to regular call. 1331592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (!object->IsJSArray() || !cell.is_null()) { 1332592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return Handle<Code>::null(); 133344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 13346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss; 13366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateNameCheck(name, &miss); 13387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the receiver from the stack. 13406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int argc = arguments().immediate(); 13416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 13426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the receiver isn't a smi. 13443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &miss); 13456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1346592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, 1347592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch name, &miss); 13486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (argc == 0) { 13506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Noop, return the length. 13516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); 13526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret((argc + 1) * kPointerSize); 13536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 1354756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label call_builtin; 1355756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 13566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the elements array of the object. 13576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); 13586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1359756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Check that the elements are in fast mode and writable. 13606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 136144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Immediate(factory()->fixed_array_map())); 1362756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ j(not_equal, &call_builtin); 13636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (argc == 1) { // Otherwise fall through to call builtin. 1365592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Label attempt_to_grow_elements, with_write_barrier; 13666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the array's length into eax and calculate new length. 13686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); 13696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block STATIC_ASSERT(kSmiTagSize == 1); 13706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block STATIC_ASSERT(kSmiTag == 0); 1371592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ add(eax, Immediate(Smi::FromInt(argc))); 13726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the element's length into ecx. 13746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ecx, FieldOperand(ebx, FixedArray::kLengthOffset)); 13756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check if we could survive without allocation. 1377592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(eax, ecx); 13786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(greater, &attempt_to_grow_elements); 13796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1380592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Check if value is a smi. 1381592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(ecx, Operand(esp, argc * kPointerSize)); 1382592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ JumpIfNotSmi(ecx, &with_write_barrier); 1383592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 13846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Save new length. 13856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); 13866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Push the element. 13886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ lea(edx, FieldOperand(ebx, 13896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block eax, times_half_pointer_size, 13906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FixedArray::kHeaderSize - argc * kPointerSize)); 13916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(Operand(edx, 0), ecx); 13926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret((argc + 1) * kPointerSize); 13946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&with_write_barrier); 13966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1397592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); 1398592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ CheckFastObjectElements(edi, &call_builtin); 1399592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1400592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Save new length. 1401592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); 1402592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1403592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Push the element. 1404592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ lea(edx, FieldOperand(ebx, 1405592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch eax, times_half_pointer_size, 1406592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch FixedArray::kHeaderSize - argc * kPointerSize)); 1407592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(Operand(edx, 0), ecx); 1408592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1409592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ RecordWrite(ebx, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, 1410592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch OMIT_SMI_CHECK); 14116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret((argc + 1) * kPointerSize); 14136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&attempt_to_grow_elements); 14155913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!FLAG_inline_new) { 14165913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck __ jmp(&call_builtin); 14175913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 14185913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 1419592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(edi, Operand(esp, argc * kPointerSize)); 1420592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Growing elements that are SMI-only requires special handling in case 1421592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // the new element is non-Smi. For now, delegate to the builtin. 1422592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Label no_fast_elements_check; 1423592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ JumpIfSmi(edi, &no_fast_elements_check); 1424592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 1425592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ CheckFastObjectElements(ecx, &call_builtin, Label::kFar); 1426592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(&no_fast_elements_check); 1427592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1428592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // We could be lucky and the elements array could be at the top of 1429592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // new-space. In this case we can just grow it in place by moving the 1430592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // allocation pointer up. 1431592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 14326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference new_space_allocation_top = 143344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::new_space_allocation_top_address(isolate()); 14346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference new_space_allocation_limit = 143544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::new_space_allocation_limit_address(isolate()); 14366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kAllocationDelta = 4; 14386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Load top. 14396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ecx, Operand::StaticVariable(new_space_allocation_top)); 14406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check if it's the end of elements. 14426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ lea(edx, FieldOperand(ebx, 14436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block eax, times_half_pointer_size, 14446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FixedArray::kHeaderSize - argc * kPointerSize)); 1445592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(edx, ecx); 14466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_equal, &call_builtin); 1447592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ add(ecx, Immediate(kAllocationDelta * kPointerSize)); 14486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(ecx, Operand::StaticVariable(new_space_allocation_limit)); 14496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(above, &call_builtin); 14506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // We fit and could grow elements. 14526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(Operand::StaticVariable(new_space_allocation_top), ecx); 14536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Push the argument... 1455592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(Operand(edx, 0), edi); 14566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ... and fill the rest with holes. 14576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (int i = 1; i < kAllocationDelta; i++) { 14586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(Operand(edx, i * kPointerSize), 145944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Immediate(factory()->the_hole_value())); 14606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 14616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1462592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // We know the elements array is in new space so we don't need the 1463592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // remembered set, but we just pushed a value onto it so we may have to 1464592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // tell the incremental marker to rescan the object that we just grew. We 1465592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // don't need to worry about the holes because they are in old space and 1466592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // already marked black. 1467592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ RecordWrite(ebx, edx, edi, kDontSaveFPRegs, OMIT_REMEMBERED_SET); 1468592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 14696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Restore receiver to edx as finish sequence assumes it's here. 14706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 14716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Increment element's and array's sizes. 14736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ add(FieldOperand(ebx, FixedArray::kLengthOffset), 14747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Immediate(Smi::FromInt(kAllocationDelta))); 1475592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1476592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // NOTE: This only happen in new-space, where we don't 1477592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // care about the black-byte-count on pages. Otherwise we should 1478592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // update that too if the object is black. 1479592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 14806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); 14816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret((argc + 1) * kPointerSize); 14836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 14846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1485756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ bind(&call_builtin); 148644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ TailCallExternalReference( 148744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(Builtins::c_ArrayPush, isolate()), 148844f0eee88ff00398ff7f715fab053374d808c90dSteve Block argc + 1, 148944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1); 14906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 14916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss); 1493592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateMissBranch(); 14946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return the generated code. 149625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen return GetCode(function); 14976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 14986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1500592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> CallStubCompiler::CompileArrayPopCall( 1501592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Object> object, 1502592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder, 1503592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSGlobalPropertyCell> cell, 1504592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSFunction> function, 1505592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name) { 15066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 15076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : name 15086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[0] : return address 15096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[(argc - n) * 4] : arg[n] (zero-based) 15106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ... 15116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[(argc + 1) * 4] : receiver 15126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 15136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // If object is not an array, bail out to regular call. 1515592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (!object->IsJSArray() || !cell.is_null()) { 1516592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return Handle<Code>::null(); 151744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 15186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss, return_undefined, call_builtin; 15206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateNameCheck(name, &miss); 15227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 15236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the receiver from the stack. 15246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int argc = arguments().immediate(); 15256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 15266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the receiver isn't a smi. 15283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &miss); 1529592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, 1530592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch name, &miss); 15316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the elements array of the object. 15336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); 15346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1535756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Check that the elements are in fast mode and writable. 15366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 153744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Immediate(factory()->fixed_array_map())); 1538756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ j(not_equal, &call_builtin); 15396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the array's length into ecx and calculate new length. 15416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ecx, FieldOperand(edx, JSArray::kLengthOffset)); 1542592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ sub(ecx, Immediate(Smi::FromInt(1))); 15436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(negative, &return_undefined); 15446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the last element. 15466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block STATIC_ASSERT(kSmiTagSize == 1); 15476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block STATIC_ASSERT(kSmiTag == 0); 15486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(eax, FieldOperand(ebx, 15496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ecx, times_half_pointer_size, 15506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FixedArray::kHeaderSize)); 1551592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(eax, Immediate(factory()->the_hole_value())); 15526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(equal, &call_builtin); 15536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Set the array's length. 15556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(FieldOperand(edx, JSArray::kLengthOffset), ecx); 15566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Fill with the hole. 15586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(FieldOperand(ebx, 15596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ecx, times_half_pointer_size, 15606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FixedArray::kHeaderSize), 156144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Immediate(factory()->the_hole_value())); 15626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret((argc + 1) * kPointerSize); 15636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&return_undefined); 156544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(eax, Immediate(factory()->undefined_value())); 15666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret((argc + 1) * kPointerSize); 15676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&call_builtin); 156944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ TailCallExternalReference( 157044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(Builtins::c_ArrayPop, isolate()), 157144f0eee88ff00398ff7f715fab053374d808c90dSteve Block argc + 1, 157244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1); 15736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss); 1575592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateMissBranch(); 15767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 15777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Return the generated code. 15787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch return GetCode(function); 15797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 15807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 15817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1582592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> CallStubCompiler::CompileStringCharCodeAtCall( 1583592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Object> object, 1584592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder, 1585592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSGlobalPropertyCell> cell, 1586592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSFunction> function, 1587592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name) { 15887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------- S t a t e ------------- 15897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ecx : function name 15907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[0] : return address 15917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc - n) * 4] : arg[n] (zero-based) 15927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ... 15937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc + 1) * 4] : receiver 15947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------------------------------- 15957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1596756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // If object is not a string, bail out to regular call. 1597592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (!object->IsString() || !cell.is_null()) { 1598592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return Handle<Code>::null(); 159944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1600756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 16017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch const int argc = arguments().immediate(); 16027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label miss; 1604b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label name_miss; 16057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 1606b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label* index_out_of_range_label = &index_out_of_range; 16079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 1608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (kind_ == Code::CALL_IC && 1609592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch (CallICBase::StringStubState::decode(extra_state_) == 1610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DEFAULT_STRING_STUB)) { 1611b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch index_out_of_range_label = &miss; 1612b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1613b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1614b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch GenerateNameCheck(name, &name_miss); 16157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps starting from the prototype haven't changed. 16177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype(masm(), 16187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Context::STRING_FUNCTION_INDEX, 16190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen eax, 16200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &miss); 1621592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT(!object.is_identical_to(holder)); 1622592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())), 1623592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch eax, holder, ebx, edx, edi, name, &miss); 16247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register receiver = ebx; 16267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = edi; 16277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = eax; 16287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); 16297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (argc > 0) { 16307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); 16317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 163244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Set(index, Immediate(factory()->undefined_value())); 16337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 16347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1635592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch StringCharCodeAtGenerator generator(receiver, 1636592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch index, 1637592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch result, 1638592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch &miss, // When not a string. 1639592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch &miss, // When not a number. 1640592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch index_out_of_range_label, 1641592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch STRING_INDEX_IS_NUMBER); 1642592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch generator.GenerateFast(masm()); 16437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ ret((argc + 1) * kPointerSize); 16447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch StubRuntimeCallHelper call_helper; 1646592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch generator.GenerateSlow(masm(), call_helper); 16477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1648b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (index_out_of_range.is_linked()) { 1649b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&index_out_of_range); 165044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Set(eax, Immediate(factory()->nan_value())); 1651b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ ret((argc + 1) * kPointerSize); 1652b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 16537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&miss); 1655b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Restore function name in ecx. 1656592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ Set(ecx, Immediate(name)); 1657b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&name_miss); 1658592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateMissBranch(); 16597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Return the generated code. 16617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch return GetCode(function); 16627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 16637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1665592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> CallStubCompiler::CompileStringCharAtCall( 1666592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Object> object, 1667592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder, 1668592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSGlobalPropertyCell> cell, 1669592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSFunction> function, 1670592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name) { 16717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------- S t a t e ------------- 16727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ecx : function name 16737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[0] : return address 16747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc - n) * 4] : arg[n] (zero-based) 16757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ... 16767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc + 1) * 4] : receiver 16777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------------------------------- 16787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1679756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // If object is not a string, bail out to regular call. 1680592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (!object->IsString() || !cell.is_null()) { 1681592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return Handle<Code>::null(); 168244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1683756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 16847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch const int argc = arguments().immediate(); 16857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label miss; 1687b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label name_miss; 16887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 1689b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label* index_out_of_range_label = &index_out_of_range; 16907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (kind_ == Code::CALL_IC && 1692592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch (CallICBase::StringStubState::decode(extra_state_) == 1693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DEFAULT_STRING_STUB)) { 1694b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch index_out_of_range_label = &miss; 1695b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1696b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1697b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch GenerateNameCheck(name, &name_miss); 16987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps starting from the prototype haven't changed. 17007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype(masm(), 17017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Context::STRING_FUNCTION_INDEX, 17020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen eax, 17030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &miss); 1704592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT(!object.is_identical_to(holder)); 1705592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())), 1706592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch eax, holder, ebx, edx, edi, name, &miss); 17077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register receiver = eax; 17097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = edi; 1710592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register scratch = edx; 17117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = eax; 17127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); 17137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (argc > 0) { 17147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); 17157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 171644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Set(index, Immediate(factory()->undefined_value())); 17177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 17187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1719592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch StringCharAtGenerator generator(receiver, 1720592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch index, 1721592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch scratch, 1722592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch result, 1723592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch &miss, // When not a string. 1724592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch &miss, // When not a number. 1725592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch index_out_of_range_label, 1726592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch STRING_INDEX_IS_NUMBER); 1727592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch generator.GenerateFast(masm()); 17287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ ret((argc + 1) * kPointerSize); 17297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch StubRuntimeCallHelper call_helper; 1731592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch generator.GenerateSlow(masm(), call_helper); 17327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1733b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (index_out_of_range.is_linked()) { 1734b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&index_out_of_range); 173544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Set(eax, Immediate(factory()->empty_string())); 1736b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ ret((argc + 1) * kPointerSize); 1737b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 17387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&miss); 1740b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Restore function name in ecx. 1741592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ Set(ecx, Immediate(name)); 1742b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&name_miss); 1743592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateMissBranch(); 17446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return the generated code. 174625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen return GetCode(function); 17476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 17486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1750592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> CallStubCompiler::CompileStringFromCharCodeCall( 1751592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Object> object, 1752592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder, 1753592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSGlobalPropertyCell> cell, 1754592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSFunction> function, 1755592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name) { 175659151504615d929945dc59db37bf1166937748c6Steve Block // ----------- S t a t e ------------- 175759151504615d929945dc59db37bf1166937748c6Steve Block // -- ecx : function name 175859151504615d929945dc59db37bf1166937748c6Steve Block // -- esp[0] : return address 175959151504615d929945dc59db37bf1166937748c6Steve Block // -- esp[(argc - n) * 4] : arg[n] (zero-based) 176059151504615d929945dc59db37bf1166937748c6Steve Block // -- ... 176159151504615d929945dc59db37bf1166937748c6Steve Block // -- esp[(argc + 1) * 4] : receiver 176259151504615d929945dc59db37bf1166937748c6Steve Block // ----------------------------------- 176359151504615d929945dc59db37bf1166937748c6Steve Block 176459151504615d929945dc59db37bf1166937748c6Steve Block const int argc = arguments().immediate(); 176559151504615d929945dc59db37bf1166937748c6Steve Block 176659151504615d929945dc59db37bf1166937748c6Steve Block // If the object is not a JSObject or we got an unexpected number of 176759151504615d929945dc59db37bf1166937748c6Steve Block // arguments, bail out to the regular call. 176844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!object->IsJSObject() || argc != 1) { 1769592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return Handle<Code>::null(); 177044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 177159151504615d929945dc59db37bf1166937748c6Steve Block 177259151504615d929945dc59db37bf1166937748c6Steve Block Label miss; 177359151504615d929945dc59db37bf1166937748c6Steve Block GenerateNameCheck(name, &miss); 177459151504615d929945dc59db37bf1166937748c6Steve Block 1775592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (cell.is_null()) { 177659151504615d929945dc59db37bf1166937748c6Steve Block __ mov(edx, Operand(esp, 2 * kPointerSize)); 177759151504615d929945dc59db37bf1166937748c6Steve Block STATIC_ASSERT(kSmiTag == 0); 17783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &miss); 1779592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, 1780592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch name, &miss); 178159151504615d929945dc59db37bf1166937748c6Steve Block } else { 1782592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT(cell->value() == *function); 1783592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 1784592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch &miss); 178559151504615d929945dc59db37bf1166937748c6Steve Block GenerateLoadFunctionFromCell(cell, function, &miss); 178659151504615d929945dc59db37bf1166937748c6Steve Block } 178759151504615d929945dc59db37bf1166937748c6Steve Block 178859151504615d929945dc59db37bf1166937748c6Steve Block // Load the char code argument. 178959151504615d929945dc59db37bf1166937748c6Steve Block Register code = ebx; 179059151504615d929945dc59db37bf1166937748c6Steve Block __ mov(code, Operand(esp, 1 * kPointerSize)); 179159151504615d929945dc59db37bf1166937748c6Steve Block 179259151504615d929945dc59db37bf1166937748c6Steve Block // Check the code is a smi. 179359151504615d929945dc59db37bf1166937748c6Steve Block Label slow; 179459151504615d929945dc59db37bf1166937748c6Steve Block STATIC_ASSERT(kSmiTag == 0); 17953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(code, &slow); 179659151504615d929945dc59db37bf1166937748c6Steve Block 179759151504615d929945dc59db37bf1166937748c6Steve Block // Convert the smi code to uint16. 179859151504615d929945dc59db37bf1166937748c6Steve Block __ and_(code, Immediate(Smi::FromInt(0xffff))); 179959151504615d929945dc59db37bf1166937748c6Steve Block 1800592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch StringCharFromCodeGenerator generator(code, eax); 1801592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch generator.GenerateFast(masm()); 180259151504615d929945dc59db37bf1166937748c6Steve Block __ ret(2 * kPointerSize); 180359151504615d929945dc59db37bf1166937748c6Steve Block 1804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch StubRuntimeCallHelper call_helper; 1805592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch generator.GenerateSlow(masm(), call_helper); 180659151504615d929945dc59db37bf1166937748c6Steve Block 180759151504615d929945dc59db37bf1166937748c6Steve Block // Tail call the full function. We do not have to patch the receiver 180859151504615d929945dc59db37bf1166937748c6Steve Block // because the function makes no use of it. 180959151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&slow); 1810592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 1811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 1812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 1813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(function, arguments(), JUMP_FUNCTION, 1814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), call_kind); 181559151504615d929945dc59db37bf1166937748c6Steve Block 181659151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&miss); 181759151504615d929945dc59db37bf1166937748c6Steve Block // ecx: function name. 1818592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateMissBranch(); 181959151504615d929945dc59db37bf1166937748c6Steve Block 182059151504615d929945dc59db37bf1166937748c6Steve Block // Return the generated code. 1821592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); 182259151504615d929945dc59db37bf1166937748c6Steve Block} 182359151504615d929945dc59db37bf1166937748c6Steve Block 182459151504615d929945dc59db37bf1166937748c6Steve Block 1825592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> CallStubCompiler::CompileMathFloorCall( 1826592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Object> object, 1827592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder, 1828592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSGlobalPropertyCell> cell, 1829592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSFunction> function, 1830592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name) { 18310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // ----------- S t a t e ------------- 18320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // -- ecx : name 18330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // -- esp[0] : return address 18340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // -- esp[(argc - n) * 4] : arg[n] (zero-based) 18350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // -- ... 18360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // -- esp[(argc + 1) * 4] : receiver 18370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // ----------------------------------- 18380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 18398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (!CpuFeatures::IsSupported(SSE2)) { 1840592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return Handle<Code>::null(); 184144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 184244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 18430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CpuFeatures::Scope use_sse2(SSE2); 18440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 18450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen const int argc = arguments().immediate(); 18460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 18470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // If the object is not a JSObject or we got an unexpected number of 18480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // arguments, bail out to the regular call. 184944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!object->IsJSObject() || argc != 1) { 1850592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return Handle<Code>::null(); 185144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 18520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 18530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label miss; 18540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen GenerateNameCheck(name, &miss); 18550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 1856592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (cell.is_null()) { 18570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(edx, Operand(esp, 2 * kPointerSize)); 18580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 18590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen STATIC_ASSERT(kSmiTag == 0); 18603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &miss); 18610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 1862592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, 1863592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch name, &miss); 18640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 1865592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT(cell->value() == *function); 1866592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 1867592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch &miss); 18680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen GenerateLoadFunctionFromCell(cell, function, &miss); 18690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 18700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 18710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Load the (only) argument into eax. 18720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(eax, Operand(esp, 1 * kPointerSize)); 18730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 18740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Check if the argument is a smi. 18750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label smi; 18760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen STATIC_ASSERT(kSmiTag == 0); 18773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(eax, &smi); 18780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 18790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Check if the argument is a heap number and load its value into xmm0. 18800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label slow; 1881257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CheckMap(eax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK); 18820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ movdbl(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); 18830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 18840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Check if the argument is strictly positive. Note this also 18850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // discards NaN. 18860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ xorpd(xmm1, xmm1); 18870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ ucomisd(xmm0, xmm1); 18880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ j(below_equal, &slow); 18890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 18900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Do a truncating conversion. 18910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ cvttsd2si(eax, Operand(xmm0)); 18920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 18930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Check if the result fits into a smi. Note this also checks for 18940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // 0x80000000 which signals a failed conversion. 18950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label wont_fit_into_smi; 18960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ test(eax, Immediate(0xc0000000)); 18970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ j(not_zero, &wont_fit_into_smi); 18980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 18990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Smi tag and return. 19000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ SmiTag(eax); 19010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&smi); 19020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ ret(2 * kPointerSize); 19030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Check if the argument is < 2^kMantissaBits. 19050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label already_round; 19060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&wont_fit_into_smi); 19070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadPowerOf2(xmm1, ebx, HeapNumber::kMantissaBits); 19080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ ucomisd(xmm0, xmm1); 19090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ j(above_equal, &already_round); 19100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Save a copy of the argument. 19120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ movaps(xmm2, xmm0); 19130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Compute (argument + 2^kMantissaBits) - 2^kMantissaBits. 19150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ addsd(xmm0, xmm1); 19160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ subsd(xmm0, xmm1); 19170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Compare the argument and the tentative result to get the right mask: 19190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // if xmm2 < xmm0: 19200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // xmm2 = 1...1 19210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // else: 19220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // xmm2 = 0...0 19230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ cmpltsd(xmm2, xmm0); 19240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Subtract 1 if the argument was less than the tentative result. 19260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadPowerOf2(xmm1, ebx, 0); 19270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ andpd(xmm1, xmm2); 19280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ subsd(xmm0, xmm1); 19290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Return a new heap number. 19310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ AllocateHeapNumber(eax, ebx, edx, &slow); 19320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); 19330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ ret(2 * kPointerSize); 19340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Return the argument (when it's an already round heap number). 19360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&already_round); 19370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(eax, Operand(esp, 1 * kPointerSize)); 19380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ ret(2 * kPointerSize); 19390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Tail call the full function. We do not have to patch the receiver 19410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // because the function makes no use of it. 19420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&slow); 1943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(function, arguments(), JUMP_FUNCTION, 1944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), CALL_AS_METHOD); 19450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&miss); 19470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // ecx: function name. 1948592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateMissBranch(); 19490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Return the generated code. 1951592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); 19520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 19530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 1955592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> CallStubCompiler::CompileMathAbsCall( 1956592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Object> object, 1957592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder, 1958592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSGlobalPropertyCell> cell, 1959592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSFunction> function, 1960592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name) { 1961f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // ----------- S t a t e ------------- 1962f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- ecx : name 1963f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- esp[0] : return address 1964f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1965f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- ... 1966f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- esp[(argc + 1) * 4] : receiver 1967f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // ----------------------------------- 1968f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 1969f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch const int argc = arguments().immediate(); 1970f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 1971f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // If the object is not a JSObject or we got an unexpected number of 1972f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // arguments, bail out to the regular call. 197344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!object->IsJSObject() || argc != 1) { 1974592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return Handle<Code>::null(); 197544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1976f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 1977f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Label miss; 1978f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch GenerateNameCheck(name, &miss); 1979f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 1980592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (cell.is_null()) { 1981f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ mov(edx, Operand(esp, 2 * kPointerSize)); 1982f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 1983f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch STATIC_ASSERT(kSmiTag == 0); 19843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &miss); 1985f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 1986592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, 1987592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch name, &miss); 1988f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch } else { 1989592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT(cell->value() == *function); 1990592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 1991592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch &miss); 1992f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch GenerateLoadFunctionFromCell(cell, function, &miss); 1993f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch } 1994f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 1995f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Load the (only) argument into eax. 1996f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ mov(eax, Operand(esp, 1 * kPointerSize)); 1997f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 1998f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Check if the argument is a smi. 1999f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Label not_smi; 2000f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch STATIC_ASSERT(kSmiTag == 0); 20013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(eax, ¬_smi); 2002f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2003f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0 2004f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // otherwise. 2005f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ mov(ebx, eax); 2006f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ sar(ebx, kBitsPerInt - 1); 2007f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2008f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Do bitwise not or do nothing depending on ebx. 2009592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ xor_(eax, ebx); 2010f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2011f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Add 1 or do nothing depending on ebx. 2012592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ sub(eax, ebx); 2013f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2014f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // If the result is still negative, go to the slow case. 2015f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // This only happens for the most negative smi. 2016f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Label slow; 2017f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ j(negative, &slow); 2018f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2019f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Smi case done. 2020f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ ret(2 * kPointerSize); 2021f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2022f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Check if the argument is a heap number and load its exponent and 2023f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // sign into ebx. 2024f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(¬_smi); 2025257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CheckMap(eax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK); 2026f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ mov(ebx, FieldOperand(eax, HeapNumber::kExponentOffset)); 2027f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2028f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Check the sign of the argument. If the argument is positive, 2029f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // just return it. 2030f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Label negative_sign; 2031f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ test(ebx, Immediate(HeapNumber::kSignMask)); 2032f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ j(not_zero, &negative_sign); 2033f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ ret(2 * kPointerSize); 2034f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2035f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // If the argument is negative, clear the sign, and return a new 2036f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // number. 2037f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(&negative_sign); 2038f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ and_(ebx, ~HeapNumber::kSignMask); 2039f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ mov(ecx, FieldOperand(eax, HeapNumber::kMantissaOffset)); 2040f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ AllocateHeapNumber(eax, edi, edx, &slow); 2041f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ebx); 2042f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); 2043f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ ret(2 * kPointerSize); 2044f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2045f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Tail call the full function. We do not have to patch the receiver 2046f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // because the function makes no use of it. 2047f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(&slow); 2048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(function, arguments(), JUMP_FUNCTION, 2049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), CALL_AS_METHOD); 2050f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2051f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(&miss); 2052f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // ecx: function name. 2053592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateMissBranch(); 2054f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2055f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Return the generated code. 2056592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); 2057f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch} 2058f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2059f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2060592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> CallStubCompiler::CompileFastApiCall( 206144f0eee88ff00398ff7f715fab053374d808c90dSteve Block const CallOptimization& optimization, 2062592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Object> object, 2063592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder, 2064592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSGlobalPropertyCell> cell, 2065592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSFunction> function, 2066592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name) { 206744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(optimization.is_simple_api_call()); 206844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Bail out if object is a global object as we don't want to 206944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // repatch it to global receiver. 2070592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (object->IsGlobalObject()) return Handle<Code>::null(); 2071592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (!cell.is_null()) return Handle<Code>::null(); 2072592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (!object->IsJSObject()) return Handle<Code>::null(); 207344f0eee88ff00398ff7f715fab053374d808c90dSteve Block int depth = optimization.GetPrototypeDepthOfExpectedType( 2074592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject>::cast(object), holder); 2075592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (depth == kInvalidProtoDepth) return Handle<Code>::null(); 207644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 207744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label miss, miss_before_stack_reserved; 207844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 207944f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenerateNameCheck(name, &miss_before_stack_reserved); 208044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 208144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Get the receiver from the stack. 208244f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int argc = arguments().immediate(); 208344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 208444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 208544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the receiver isn't a smi. 20863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &miss_before_stack_reserved); 208744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 208844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 208944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_const(), 1); 209044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_const_fast_api(), 1); 209144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 209244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Allocate space for v8::Arguments implicit values. Must be initialized 209344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // before calling any runtime function. 2094592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ sub(esp, Immediate(kFastApiCallArguments * kPointerSize)); 209544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 209644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the maps haven't changed and find a Holder as a side effect. 2097592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, 2098592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch name, depth, &miss); 209944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 210044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Move the return address on top of the stack. 210144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(eax, Operand(esp, 3 * kPointerSize)); 210244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(Operand(esp, 0 * kPointerSize), eax); 210344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 210444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains 210544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // duplicate of return address and will be overwritten. 2106592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateFastApiCall(masm(), optimization, argc); 210744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 210844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&miss); 2109592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); 211044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 211144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&miss_before_stack_reserved); 2112592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateMissBranch(); 211344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 211444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Return the generated code. 211544f0eee88ff00398ff7f715fab053374d808c90dSteve Block return GetCode(function); 211644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 211744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 211844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2119592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object, 2120592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder, 2121592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSFunction> function, 2122592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name, 2123592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CheckType check) { 2124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2125e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 2126e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 2127e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 2128e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 2129e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 2130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 21316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 213244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (HasCustomCallGenerator(function)) { 2133592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Code> code = CompileCustomCall(object, holder, 2134592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSGlobalPropertyCell>::null(), 2135592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch function, name); 2136592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // A null handle means bail out to the regular compiler code below. 2137592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (!code.is_null()) return code; 21386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 21396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 214044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label miss; 214144f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenerateNameCheck(name, &miss); 21427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver from the stack. 2144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 2145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 2146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 2148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check != NUMBER_CHECK) { 21493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &miss); 2150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure that it's okay not to patch the on stack receiver 2153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // unless we're doing a receiver map check. 2154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); 2155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (check) { 2156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case RECEIVER_MAP_CHECK: 215744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(isolate()->counters()->call_const(), 1); 2158402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 2159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 2160592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, 2161592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch edi, name, &miss); 2162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack with the global proxy if 2164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // necessary. 2165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsGlobalObject()) { 2166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 2167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 2168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 2170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case STRING_CHECK: 2172592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (function->IsBuiltin() || !function->shared()->is_classic_mode()) { 2173e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the object is a string or a symbol. 21747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax); 2175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above_equal, &miss); 2176e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the maps starting from the prototype haven't changed. 21777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype( 21780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen masm(), Context::STRING_FUNCTION_INDEX, eax, &miss); 2179592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CheckPrototypes( 2180592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject>(JSObject::cast(object->GetPrototype())), 2181592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch eax, holder, ebx, edx, edi, name, &miss); 2182592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } else { 2183e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Calling non-strict non-builtins with a value as the receiver 2184e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // requires boxing. 2185e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(&miss); 2186592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 2187592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch break; 2188592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 2189592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch case NUMBER_CHECK: 2190592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (function->IsBuiltin() || !function->shared()->is_classic_mode()) { 2191e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label fast; 2192e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the object is a smi or a heap number. 21933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &fast); 2194e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); 2195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2196e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&fast); 2197e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the maps starting from the prototype haven't changed. 21987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype( 21990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss); 2200592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CheckPrototypes( 2201592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject>(JSObject::cast(object->GetPrototype())), 2202592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch eax, holder, ebx, edx, edi, name, &miss); 2203592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } else { 2204e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Calling non-strict non-builtins with a value as the receiver 2205e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // requires boxing. 2206e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(&miss); 2207592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 2208592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch break; 2209592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 2210592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch case BOOLEAN_CHECK: 2211592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (function->IsBuiltin() || !function->shared()->is_classic_mode()) { 2212e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label fast; 2213e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the object is a boolean. 221444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(edx, factory()->true_value()); 2215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &fast); 221644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(edx, factory()->false_value()); 2217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2218e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&fast); 2219e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the maps starting from the prototype haven't changed. 22207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype( 22210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss); 2222592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CheckPrototypes( 2223592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject>(JSObject::cast(object->GetPrototype())), 2224592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch eax, holder, ebx, edx, edi, name, &miss); 2225592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } else { 2226592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Calling non-strict non-builtins with a value as the receiver 2227592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // requires boxing. 2228592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ jmp(&miss); 2229e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 2231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2233592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 2235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 2236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(function, arguments(), JUMP_FUNCTION, 2237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), call_kind); 2238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 2240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2241592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateMissBranch(); 2242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 224425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen return GetCode(function); 2245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2248592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, 2249592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder, 2250592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name) { 2251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2252e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 2253e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 2254e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 2255e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 2256e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 2257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 22607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateNameCheck(name, &miss); 22617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the number of arguments. 2263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 2264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2265592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch LookupResult lookup(isolate()); 2266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupPostInterceptor(holder, name, &lookup); 2267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver from the stack. 2269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 2270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2271592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CallInterceptorCompiler compiler(this, arguments(), ecx, extra_state_); 2272592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch compiler.Compile(masm(), object, holder, name, &lookup, edx, ebx, edi, eax, 2273592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch &miss); 2274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore receiver. 2276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 2277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the function really is a function. 22793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(eax, &miss); 2280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); 2281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack with the global proxy if 2284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // necessary. 2285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsGlobalObject()) { 2286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 2287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 2288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the function. 2291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edi, eax); 2292592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 2294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 2295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, 2296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), call_kind); 2297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle load cache miss. 2299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2300592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateMissBranch(); 2301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2307592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> CallStubCompiler::CompileCallGlobal( 2308592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> object, 2309592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<GlobalObject> holder, 2310592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSGlobalPropertyCell> cell, 2311592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSFunction> function, 2312592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name) { 2313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 2315e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 2316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 2317e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 2318e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 2319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 232059151504615d929945dc59db37bf1166937748c6Steve Block 232144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (HasCustomCallGenerator(function)) { 2322592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Code> code = CompileCustomCall(object, holder, cell, function, name); 2323592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // A null handle means bail out to the regular compiler code below. 2324592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (!code.is_null()) return code; 232559151504615d929945dc59db37bf1166937748c6Steve Block } 232659151504615d929945dc59db37bf1166937748c6Steve Block 2327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 23287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateNameCheck(name, &miss); 23297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the number of arguments. 2331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 233259151504615d929945dc59db37bf1166937748c6Steve Block GenerateGlobalReceiverCheck(object, holder, name, &miss); 233359151504615d929945dc59db37bf1166937748c6Steve Block GenerateLoadFunctionFromCell(cell, function, &miss); 2334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack with the global proxy. 2336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsGlobalObject()) { 2337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 2338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 2339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Setup the context (function already in edi). 2342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 2343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the cached code (tail call). 234544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 234644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_global_inline(), 1); 2347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount expected(function->shared()->formal_parameter_count()); 2348592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 2350257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 2351592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // We call indirectly through the code field in the function to 2352592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // allow recompilation to take effect without changing any of the 2353592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // call sites. 2354592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), 2355592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch expected, arguments(), JUMP_FUNCTION, 2356592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch NullCallWrapper(), call_kind); 2357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 2359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 236044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_global_inline_miss(), 1); 2361592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateMissBranch(); 2362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(NORMAL, name); 2365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2368592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, 23695913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index, 2370592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Map> transition, 2371592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name) { 2372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 2374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 23754515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- edx : receiver 2376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Generate store field code. Trashes the name register. 2381592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateStoreField(masm(), object, index, transition, edx, ecx, ebx, &miss); 2382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2385592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(ecx, Immediate(name)); // restore name 238644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); 2387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(ic, RelocInfo::CODE_TARGET); 2388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2390592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); 2391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2394592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> StoreStubCompiler::CompileStoreCallback( 2395592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> object, 2396592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<AccessorInfo> callback, 2397592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name) { 2398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 2400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 24014515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- edx : receiver 2402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object isn't a smi. 24073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &miss); 2408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the object hasn't changed. 24104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ cmp(FieldOperand(edx, HeapObject::kMapOffset), 2411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(Handle<Map>(object->map()))); 2412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform global security token check if needed. 2415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsJSGlobalProxy()) { 24164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CheckAccessGlobalProxy(edx, ebx, &miss); 2417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stub never generated for non-global objects that require access 2420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks. 2421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 2422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); // remove the return address 24244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(edx); // receiver 2425592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(Immediate(callback)); // callback info 2426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); // name 2427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(eax); // value 2428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); // restore return address 2429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to the runtime system. 2431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference store_callback_property = 243244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); 24336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(store_callback_property, 4, 1); 2434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 243744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); 2438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(ic, RelocInfo::CODE_TARGET); 2439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2445592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> StoreStubCompiler::CompileStoreInterceptor( 2446592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> receiver, 2447592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name) { 2448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 2450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 24514515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- edx : receiver 2452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object isn't a smi. 24573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &miss); 2458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the object hasn't changed. 24604515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ cmp(FieldOperand(edx, HeapObject::kMapOffset), 2461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(Handle<Map>(receiver->map()))); 2462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform global security token check if needed. 2465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (receiver->IsJSGlobalProxy()) { 24664515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CheckAccessGlobalProxy(edx, ebx, &miss); 2467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stub never generated for non-global objects that require access 2470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks. 2471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); 2472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); // remove the return address 24744515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(edx); // receiver 2475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); // name 2476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(eax); // value 2477e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(Immediate(Smi::FromInt(strict_mode_))); 2478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); // restore return address 2479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to the runtime system. 2481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference store_ic_property = 248244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); 2483e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ TailCallExternalReference(store_ic_property, 4, 1); 2484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 248744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); 2488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(ic, RelocInfo::CODE_TARGET); 2489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2495592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> StoreStubCompiler::CompileStoreGlobal( 2496592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<GlobalObject> object, 2497592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSGlobalPropertyCell> cell, 2498592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name) { 2499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 2501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 25024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- edx : receiver 2503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the global has not changed. 25084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ cmp(FieldOperand(edx, HeapObject::kMapOffset), 2509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(Handle<Map>(object->map()))); 2510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Compute the cell operand to use. 2513592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(ebx, Immediate(cell)); 2514592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Operand cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset); 2515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the value in the cell is not the hole. If it is, this 25171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // cell could have been deleted and reintroducing the global needs 25181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // to update the property details in the property dictionary of the 25191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // global object. We bail out to the runtime system to do that. 252044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(cell_operand, factory()->the_hole_value()); 25211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(equal, &miss); 25221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 25231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Store the value in the cell. 25241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(cell_operand, eax); 2525592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // No write barrier here, because cells are always rescanned. 25261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the value (register eax). 252844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 252944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_store_global_inline(), 1); 2530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 2531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 253444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_store_global_inline_miss(), 1); 253544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); 2536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(ic, RelocInfo::CODE_TARGET); 2537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(NORMAL, name); 2540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2543592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object, 25445913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index, 2545592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Map> transition, 2546592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name) { 2547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 25496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : key 25506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- edx : receiver 2551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 255544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 255644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_store_field(), 1); 2557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 2559592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(ecx, Immediate(name)); 2560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Generate store field code. Trashes the name register. 2563592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateStoreField(masm(), object, index, transition, edx, ecx, ebx, &miss); 2564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 256744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_store_field(), 1); 256844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(ic, RelocInfo::CODE_TARGET); 2570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2572592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); 2573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2576592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreElement( 2577592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Map> receiver_map) { 2578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------- S t a t e ------------- 2579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- eax : value 2580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- ecx : key 2581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- edx : receiver 2582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- esp[0] : return address 2583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------------------------------- 2584589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind = receiver_map->elements_kind(); 25853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE; 2586592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Code> stub = 2587592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch KeyedStoreElementStub(is_jsarray, elements_kind).GetCode(); 2588592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 2589592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); 2590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(ic, RelocInfo::CODE_TARGET); 2593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 2595592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return GetCode(NORMAL, factory()->empty_string()); 2596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2599592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( 2600592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch MapHandleList* receiver_maps, 2601592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CodeHandleList* handler_stubs, 2602592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch MapHandleList* transitioned_maps) { 2603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- eax : value 2605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ecx : key 2606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- edx : receiver 2607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- esp[0] : return address 2608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 2610592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ JumpIfSmi(edx, &miss, Label::kNear); 2611592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); 2612592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // ebx: receiver->map(). 2613592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch for (int i = 0; i < receiver_maps->length(); ++i) { 2614592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(edi, receiver_maps->at(i)); 2615592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (transitioned_maps->at(i).is_null()) { 2616592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ j(equal, handler_stubs->at(i)); 2617592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } else { 2618592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Label next_map; 2619592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ j(not_equal, &next_map, Label::kNear); 2620592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(ebx, Immediate(transitioned_maps->at(i))); 2621592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET); 2622592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(&next_map); 2623592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 2624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&miss); 2626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2627257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(miss_ic, RelocInfo::CODE_TARGET); 2628e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2629e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Return the generated code. 2630592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); 2631e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2632e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2633e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2634592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name, 2635592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> object, 2636592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> last) { 26376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 26386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- eax : receiver 26396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : name 26406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[0] : return address 26416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 26426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss; 26436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 26446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the receiver isn't a smi. 26453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(eax, &miss); 26466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 26478defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(last->IsGlobalObject() || last->HasFastProperties()); 26488defd9ff6930b4e24729971a61cf7469daf119beSteve Block 26496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check the maps of the full prototype chain. Also check that 26506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // global property cells up to (but not including) the last object 26516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // in the prototype chain are empty. 26523bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss); 26536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 26546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // If the last object in the prototype chain is a global object, 26556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // check that the global property cell is empty. 26566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (last->IsGlobalObject()) { 2657592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateCheckPropertyCell( 2658592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch masm(), Handle<GlobalObject>::cast(last), name, edx, &miss); 26596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 26606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 26616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return undefined if maps of the full prototype chain are still the 26626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // same and no global property with this name contains a value. 266344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(eax, isolate()->factory()->undefined_value()); 26646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret(0); 26656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 26666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss); 26676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 26686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 26696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return the generated code. 2670592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return GetCode(NONEXISTENT, factory()->empty_string()); 26716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 26726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2674592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object, 2675592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder, 26765913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index, 2677592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name) { 2678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2679402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 2680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 2681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 26853bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch GenerateLoadField(object, holder, eax, ebx, edx, edi, index, name, &miss); 2686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(FIELD, name); 2691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2694592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> LoadStubCompiler::CompileLoadCallback( 2695592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name, 2696592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> object, 2697592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder, 2698592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<AccessorInfo> callback) { 2699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2700402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 2701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 2702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2706592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateLoadCallback(object, holder, eax, ecx, ebx, edx, edi, callback, 2707592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch name, &miss); 2708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2716592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object, 2717592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder, 2718592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Object> value, 2719592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name) { 2720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2721402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 2722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 2723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch GenerateLoadConstant(object, holder, eax, ebx, edx, edi, value, name, &miss); 2728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CONSTANT_FUNCTION, name); 2733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2736592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> receiver, 2737592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder, 2738592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name) { 2739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2740402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 2741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 2742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2746592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch LookupResult lookup(isolate()); 2747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupPostInterceptor(holder, name, &lookup); 2748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // TODO(368): Compile in the whole chain: all the interceptors in 2750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // prototypes and ultimate answer. 2751592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateLoadInterceptor(receiver, holder, &lookup, eax, ecx, edx, ebx, edi, 2752592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch name, &miss); 2753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2762592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> LoadStubCompiler::CompileLoadGlobal( 2763592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> object, 2764592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<GlobalObject> holder, 2765592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSGlobalPropertyCell> cell, 2766592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name, 2767592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch bool is_dont_delete) { 2768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2769402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 2770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 2771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the object is the holder then we know that it's a global 2776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object which can only happen for contextual loads. In this case, 2777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the receiver cannot be a smi. 2778592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (!object.is_identical_to(holder)) { 27793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(eax, &miss); 2780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 27833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CheckPrototypes(object, eax, holder, ebx, edx, edi, name, &miss); 2784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the value from the cell. 2786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (Serializer::enabled()) { 2787592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(ebx, Immediate(cell)); 2788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); 2789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 2790592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(ebx, Operand::Cell(cell)); 2791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for deleted property if property can actually be deleted. 2794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!is_dont_delete) { 279544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(ebx, factory()->the_hole_value()); 2796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &miss); 2797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (FLAG_debug_code) { 279844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(ebx, factory()->the_hole_value()); 2799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Check(not_equal, "DontDelete cells can't contain the hole"); 2800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 280244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 280344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_load_global_stub(), 1); 2804402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, ebx); 2805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 2806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 280844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_load_global_stub_miss(), 1); 2809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(NORMAL, name); 2813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2816592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name, 2817592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> receiver, 2818592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder, 28195913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index) { 2820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2821402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 2822402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 2823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 282744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 282844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_field(), 1); 2829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 2831592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(eax, Immediate(name)); 2832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); 2835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 283744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_field(), 1); 2838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(FIELD, name); 2842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2845592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadCallback( 2846592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name, 2847592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> receiver, 2848592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder, 2849592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<AccessorInfo> callback) { 2850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2851402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 2852402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 2853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 285744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 285844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_callback(), 1); 2859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 2861592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(eax, Immediate(name)); 2862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2864592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateLoadCallback(receiver, holder, edx, eax, ebx, ecx, edi, callback, 2865592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch name, &miss); 2866e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 286844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_callback(), 1); 2869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2876592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadConstant( 2877592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name, 2878592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> receiver, 2879592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder, 2880592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Object> value) { 2881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2882402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 2883402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 2884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 288844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 288944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_constant_function(), 1); 2890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 2892592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(eax, Immediate(name)); 2893257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2895592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateLoadConstant( 2896592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch receiver, holder, edx, ebx, ecx, edi, value, name, &miss); 2897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 289844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_constant_function(), 1); 2899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CONSTANT_FUNCTION, name); 2903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2906592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor( 2907592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> receiver, 2908592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> holder, 2909592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name) { 2910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2911402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 2912402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 2913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 291744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 291844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_interceptor(), 1); 2919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 2921592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(eax, Immediate(name)); 2922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2924592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch LookupResult lookup(isolate()); 2925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupPostInterceptor(holder, name, &lookup); 2926592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch GenerateLoadInterceptor(receiver, holder, &lookup, edx, eax, ecx, ebx, edi, 2927592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch name, &miss); 2928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 292944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_interceptor(), 1); 2930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2937592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength( 2938592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name) { 2939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2940402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 2941402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 2942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 294644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 294744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_array_length(), 1); 2948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 2950592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(eax, Immediate(name)); 2951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2953402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateLoadArrayLength(masm(), edx, ecx, &miss); 2954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 295544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_array_length(), 1); 2956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2963592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadStringLength( 2964592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name) { 2965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2966402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 2967402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 2968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 297244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 297344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_string_length(), 1); 2974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 2976592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(eax, Immediate(name)); 2977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true); 2980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 298144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_string_length(), 1); 2982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2989592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype( 2990592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name) { 2991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2992402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 2993402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 2994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 299844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 299944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_function_prototype(), 1); 3000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 3002592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(eax, Immediate(name)); 3003257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 3004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3005402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); 3006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 300744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_function_prototype(), 1); 3008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 3011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 3012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3015592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadElement( 3016592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Map> receiver_map) { 3017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------- S t a t e ------------- 3018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- eax : key 3019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- edx : receiver 3020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- esp[0] : return address 3021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------------------------------- 3022592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 3023589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind = receiver_map->elements_kind(); 3024592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode(); 3025592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 3026592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); 3027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3028257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3030257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 3031592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return GetCode(NORMAL, factory()->empty_string()); 3032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3035592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( 3036592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch MapHandleList* receiver_maps, 3037592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CodeHandleList* handler_ics) { 3038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- eax : key 3040257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- edx : receiver 3041257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- esp[0] : return address 3042257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3043257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 3044257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(edx, &miss); 3045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register map_reg = ebx; 3047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(map_reg, FieldOperand(edx, HeapObject::kMapOffset)); 3048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int receiver_count = receiver_maps->length(); 3049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int current = 0; current < receiver_count; ++current) { 3050592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(map_reg, receiver_maps->at(current)); 3051592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ j(equal, handler_ics->at(current)); 3052257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&miss); 3055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Return the generated code. 3058592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); 3059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Specialized stub for constructing objects from functions which only have only 3063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// simple assignments of the form this.x = ...; in their body. 3064592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHandle<Code> ConstructStubCompiler::CompileConstructStub( 3065592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSFunction> function) { 3066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 3067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : argc 3068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- edi : constructor 3069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 3070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[4] : last argument 3071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 3072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label generic_stub_call; 3073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 3074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check to see whether there are any break points in the function code. If 3075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // there are jump to the generic constructor stub which calls the actual 3076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // code for the function thereby hitting the break points. 3077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 3078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kDebugInfoOffset)); 307944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(ebx, factory()->undefined_value()); 3080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &generic_stub_call); 3081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 3082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the initial map and verify that it is in fact a map. 3084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); 3085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Will both indicate a NULL and a Smi. 30863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(ebx, &generic_stub_call); 3087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpObjectType(ebx, MAP_TYPE, ecx); 3088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &generic_stub_call); 3089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 3091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cannot construct functions this way. 3092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edi: constructor 3093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ebx: initial map 3094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpInstanceType(ebx, JS_FUNCTION_TYPE); 3095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Assert(not_equal, "Function constructed by construct stub."); 3096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 3097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Now allocate the JSObject on the heap by moving the new space allocation 3099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // top forward. 3100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edi: constructor 3101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ebx: initial map 3102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset)); 3103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ shl(ecx, kPointerSizeLog2); 3104592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ AllocateInNewSpace(ecx, edx, ecx, no_reg, 3105592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch &generic_stub_call, NO_ALLOCATION_FLAGS); 3106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocated the JSObject, now initialize the fields and add the heap tag. 3108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ebx: initial map 3109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edx: JSObject (untagged) 3110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(edx, JSObject::kMapOffset), ebx); 311144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(ebx, factory()->empty_fixed_array()); 3112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(edx, JSObject::kPropertiesOffset), ebx); 3113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(edx, JSObject::kElementsOffset), ebx); 3114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push the allocated object to the stack. This is the object that will be 3116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // returned (after it is tagged). 3117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(edx); 3118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: argc 3120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edx: JSObject (untagged) 3121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the address of the first in-object property into edx. 3122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(edx, Operand(edx, JSObject::kHeaderSize)); 3123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the location of the first argument. The stack contains the 3124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // allocated object and the return address on top of the argc arguments. 3125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(ecx, Operand(esp, eax, times_4, 1 * kPointerSize)); 3126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use edi for holding undefined which is used in several places below. 312844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(edi, factory()->undefined_value()); 3129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: argc 3131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ecx: first argument 3132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edx: first in-object property of the JSObject 3133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edi: undefined 3134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the initialized properties with a constant value or a passed argument 3135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // depending on the this.x = ...; assignment in the function. 3136592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<SharedFunctionInfo> shared(function->shared()); 3137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < shared->this_property_assignments_count(); i++) { 3138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (shared->IsThisPropertyAssignmentArgument(i)) { 3139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the argument assigned to the property is actually passed. 3140e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // If argument is not passed the property is set to undefined, 3141e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // otherwise find it on the stack. 3142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int arg_number = shared->GetThisPropertyAssignmentArgument(i); 3143e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(ebx, edi); 3144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, arg_number); 31458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CpuFeatures::IsSupported(CMOV)) { 3146e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke CpuFeatures::Scope use_cmov(CMOV); 3147e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmov(above, ebx, Operand(ecx, arg_number * -kPointerSize)); 3148e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 3149e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label not_passed; 3150e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(below_equal, ¬_passed); 3151e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(ebx, Operand(ecx, arg_number * -kPointerSize)); 3152e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(¬_passed); 3153e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3154e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store value in the property. 3155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(edx, i * kPointerSize), ebx); 3156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 3157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the property to the constant value. 3158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i)); 3159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(edx, i * kPointerSize), Immediate(constant)); 3160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the unused in-object property fields with undefined. 31648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ASSERT(function->has_initial_map()); 3165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = shared->this_property_assignments_count(); 31668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang i < function->initial_map()->inobject_properties(); 3167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i++) { 3168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(edx, i * kPointerSize), edi); 3169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move argc to ebx and retrieve and tag the JSObject to return. 3172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, eax); 3173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(eax); 3174592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ or_(eax, Immediate(kHeapObjectTag)); 3175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Remove caller arguments and receiver from the stack and return. 3177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ecx); 3178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(esp, Operand(esp, ebx, times_pointer_size, 1 * kPointerSize)); 3179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); 318044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 318144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->constructed_objects(), 1); 318244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->constructed_objects_stub(), 1); 3183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 3184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the generic stub in case the specialized code cannot handle the 3186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // construction. 3187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&generic_stub_call); 3188592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Code> code = isolate()->builtins()->JSConstructStubGeneric(); 3189592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ jmp(code, RelocInfo::CODE_TARGET); 3190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 3192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(); 3193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 31963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#undef __ 31973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#define __ ACCESS_MASM(masm) 31983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 31993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 32003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadDictionaryElement( 32013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MacroAssembler* masm) { 32021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------- S t a t e ------------- 32031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- eax : key 32041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- edx : receiver 32051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- esp[0] : return address 32061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 32073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label slow, miss_force_generic; 3208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 32093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 32103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // have been verified by the caller to not be a smi. 32113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(eax, &miss_force_generic); 32123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(ebx, eax); 32133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ SmiUntag(ebx); 32143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); 32151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 32163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Push receiver on the stack to free up a register for the dictionary 32173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // probing. 32183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ push(edx); 32193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ LoadFromNumberDictionary(&slow, 32203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ecx, 32213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch eax, 32223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ebx, 32233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch edx, 32243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch edi, 32253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch eax); 32263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Pop receiver before returning. 32273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ pop(edx); 32283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ret(0); 3229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 32303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&slow); 32313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ pop(edx); 3232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- eax : value 3235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ecx : key 3236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- edx : receiver 3237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- esp[0] : return address 3238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 32403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> slow_ic = 32413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_Slow(); 32423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(slow_ic, RelocInfo::CODE_TARGET); 3243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 32443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&miss_force_generic); 32453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------- S t a t e ------------- 32463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- eax : value 32473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- ecx : key 32483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- edx : receiver 32493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- esp[0] : return address 32503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------------------------------- 3251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 32523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> miss_force_generic_ic = 32533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 32543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(miss_force_generic_ic, RelocInfo::CODE_TARGET); 32553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 3256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadExternalArray( 3259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MacroAssembler* masm, 3260589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind) { 3261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- eax : key 3263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- edx : receiver 3264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- esp[0] : return address 3265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss_force_generic, failed_allocation, slow; 3267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 3269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 32701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 32711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the key is a smi. 32723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(eax, &miss_force_generic); 32731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 32741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the index is in range. 3275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); 327669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmp(eax, FieldOperand(ebx, ExternalArray::kLengthOffset)); 32771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Unsigned comparison catches both negative and too-large values. 3278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above_equal, &miss_force_generic); 32791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset)); 32801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ebx: base pointer of external storage 32813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3282589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 328369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ SmiUntag(eax); // Untag the index. 328469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movsx_b(eax, Operand(ebx, eax, times_1, 0)); 32851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3286589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 3287589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 328869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ SmiUntag(eax); // Untag the index. 328969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movzx_b(eax, Operand(ebx, eax, times_1, 0)); 32901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3291589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 329269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movsx_w(eax, Operand(ebx, eax, times_1, 0)); 32931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3294589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 329569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movzx_w(eax, Operand(ebx, eax, times_1, 0)); 32961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3297589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 3298589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 329969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov(ecx, Operand(ebx, eax, times_2, 0)); 33001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3301589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 330269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ fld_s(Operand(ebx, eax, times_2, 0)); 33031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3304589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 330569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ fld_d(Operand(ebx, eax, times_4, 0)); 3306257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 33071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block default: 33081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 33091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 33101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 33111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For integer array types: 33131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ecx: value 33141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For floating-point array type: 33151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // FP(0): value 33161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3317589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_INT_ELEMENTS || 3318589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { 33191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For the Int and UnsignedInt array types, we need to see whether 33201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the value can be represented in a Smi. If not, we need to convert 33211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // it to a HeapNumber. 33221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label box_int; 3323589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_INT_ELEMENTS) { 33241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmp(ecx, 0xC0000000); 33251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(sign, &box_int); 33261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 3327589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind); 33281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // The test is different for unsigned int values. Since we need 33291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the value to be in the range of a positive smi, we can't 33301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // handle either of the top two bits being set in the value. 33311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ test(ecx, Immediate(0xC0000000)); 33321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(not_zero, &box_int); 33331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 33341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(eax, ecx); 33361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ SmiTag(eax); 33371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 33381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&box_int); 33401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Allocate a HeapNumber for the int and perform int-to-double 33421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // conversion. 3343589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_INT_ELEMENTS) { 33441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(ecx); 33451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ fild_s(Operand(esp, 0)); 33461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ pop(ecx); 33471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 3348589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind); 33491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Need to zero-extend the value. 33501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // There's no fild variant for unsigned values, so zero-extend 33511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // to a 64-bit int manually. 33521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(Immediate(0)); 33531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(ecx); 33541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ fild_d(Operand(esp, 0)); 33551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ pop(ecx); 33561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ pop(ecx); 33571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 33581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // FP(0): value 33591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); 33601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Set the value. 33611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(eax, ecx); 33621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 33631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 3364589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || 3365589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 33661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For the floating-point array type, we need to always allocate a 33671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // HeapNumber. 33681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); 33691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Set the value. 33701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(eax, ecx); 33711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 33721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 33731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 33741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ SmiTag(eax); 33751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 33761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 33771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // If we fail allocation of the HeapNumber, we still have a value on 33791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // top of the FPU stack. Remove it. 33801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&failed_allocation); 3381592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ fstp(0); 33821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Fall through to slow case. 33831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Slow case: Jump to runtime. 33851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&slow); 3386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Counters* counters = masm->isolate()->counters(); 338744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_external_array_slow(), 1); 3388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 33891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------- S t a t e ------------- 33901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- eax : key 33911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- edx : receiver 33921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- esp[0] : return address 33931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 33941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Slow(); 3396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(ic, RelocInfo::CODE_TARGET); 33971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- eax : key 3400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- edx : receiver 3401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- esp[0] : return address 3402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 34031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Miss case: Jump to runtime. 3405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 3406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> miss_ic = 3407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 3408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(miss_ic, RelocInfo::CODE_TARGET); 34091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 34101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreExternalArray( 3413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MacroAssembler* masm, 3414589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind) { 34151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------- S t a t e ------------- 3416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- eax : key 34171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- edx : receiver 34181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- esp[0] : return address 34191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 3420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss_force_generic, slow, check_heap_number; 342144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 3423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 342444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 34251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the key is a smi. 34263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(ecx, &miss_force_generic); 34271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the index is in range. 342944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 343069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmp(ecx, FieldOperand(edi, ExternalArray::kLengthOffset)); 34311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Unsigned comparison catches both negative and too-large values. 34321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(above_equal, &slow); 34331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Handle both smis and HeapNumbers in the fast path. Go to the 34351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // runtime for all other kinds of values. 34361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // eax: value 34371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // edx: receiver 34381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ecx: key 34391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // edi: elements array 3440589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) { 34413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(eax, &slow); 34423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 34433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(eax, &check_heap_number); 34443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 344544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 34461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // smi case 344769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov(ebx, eax); // Preserve the value in eax as the return value. 344869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ SmiUntag(ebx); 34491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); 345069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // edi: base pointer of external storage 34513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3452589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 345369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ ClampUint8(ebx); 345469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ SmiUntag(ecx); 345569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov_b(Operand(edi, ecx, times_1, 0), ebx); 345644f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3457589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 3458589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 345969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ SmiUntag(ecx); 346069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov_b(Operand(edi, ecx, times_1, 0), ebx); 34611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3462589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 3463589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 346469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov_w(Operand(edi, ecx, times_1, 0), ebx); 34651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3466589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 3467589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 346869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov(Operand(edi, ecx, times_2, 0), ebx); 34691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3470589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 3471589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 34721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Need to perform int-to-float conversion. 347369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ push(ebx); 34741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ fild_s(Operand(esp, 0)); 347569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ pop(ebx); 3476589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 347769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ fstp_s(Operand(edi, ecx, times_2, 0)); 3478589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { // elements_kind == EXTERNAL_DOUBLE_ELEMENTS. 347969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ fstp_d(Operand(edi, ecx, times_4, 0)); 3480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 34811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 34821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block default: 34831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 34841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 34851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 34861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); // Return the original value. 34871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 348844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // TODO(danno): handle heap number -> pixel array conversion 3489589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) { 349044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&check_heap_number); 349144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // eax: value 349244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // edx: receiver 349344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // ecx: key 349444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // edi: elements array 349544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 3496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Immediate(masm->isolate()->factory()->heap_number_map())); 349744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(not_equal, &slow); 349844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 349944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // The WebGL specification leaves the behavior of storing NaN and 350044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // +/-Infinity into integer arrays basically undefined. For more 350144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // reproducible behavior, convert these to zero. 350244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); 350344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // edi: base pointer of external storage 3504589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 350544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); 350669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ fstp_s(Operand(edi, ecx, times_2, 0)); 350744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ ret(0); 3508589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 3509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); 351069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ fstp_d(Operand(edi, ecx, times_4, 0)); 3511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ret(0); 351244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 351344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Perform float-to-int conversion with truncation (round-to-zero) 351444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // behavior. 351544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 351644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // For the moment we make the slow call to the runtime on 351744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // processors that don't support SSE2. The code in IntegerConvert 351844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // (code-stubs-ia32.cc) is roughly what is needed here though the 351944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // conversion failure case does not need to be handled. 35208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CpuFeatures::IsSupported(SSE2)) { 3521589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind != EXTERNAL_INT_ELEMENTS && 3522589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch elements_kind != EXTERNAL_UNSIGNED_INT_ELEMENTS) { 35238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(CpuFeatures::IsSupported(SSE2)); 35241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CpuFeatures::Scope scope(SSE2); 352569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cvttsd2si(ebx, FieldOperand(eax, HeapNumber::kValueOffset)); 352644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // ecx: untagged integer value 35273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3528589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 352969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ ClampUint8(ebx); 353069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Fall through. 3531589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 3532589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 353369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ SmiUntag(ecx); 353469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov_b(Operand(edi, ecx, times_1, 0), ebx); 353544f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3536589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 3537589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 353869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov_w(Operand(edi, ecx, times_1, 0), ebx); 353944f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 354044f0eee88ff00398ff7f715fab053374d808c90dSteve Block default: 354144f0eee88ff00398ff7f715fab053374d808c90dSteve Block UNREACHABLE(); 354244f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 354344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 354444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 35458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CpuFeatures::IsSupported(SSE3)) { 354644f0eee88ff00398ff7f715fab053374d808c90dSteve Block CpuFeatures::Scope scope(SSE3); 354744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // fisttp stores values as signed integers. To represent the 354844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // entire range of int and unsigned int arrays, store as a 354944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // 64-bit int and discard the high 32 bits. 355044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // If the value is NaN or +/-infinity, the result is 0x80000000, 355144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // which is automatically zero when taken mod 2^n, n < 32. 355244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); 3553592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ sub(esp, Immediate(2 * kPointerSize)); 355444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ fisttp_d(Operand(esp, 0)); 355569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ pop(ebx); 3556592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ add(esp, Immediate(kPointerSize)); 355744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 35588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(CpuFeatures::IsSupported(SSE2)); 355944f0eee88ff00398ff7f715fab053374d808c90dSteve Block CpuFeatures::Scope scope(SSE2); 356044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // We can easily implement the correct rounding behavior for the 356144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // range [0, 2^31-1]. For the time being, to keep this code simple, 356244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // make the slow runtime call for values outside this range. 356344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Note: we could do better for signed int arrays. 356444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); 356544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // We will need the key if we have to make the slow runtime call. 356669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ push(ebx); 356769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ LoadPowerOf2(xmm1, ebx, 31); 356869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ pop(ebx); 356944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ ucomisd(xmm1, xmm0); 357044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(above_equal, &slow); 357169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cvttsd2si(ebx, Operand(xmm0)); 357244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 357369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // ebx: untagged integer value 357469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov(Operand(edi, ecx, times_2, 0), ebx); 35751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 357644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ ret(0); // Return original value. 35771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 35781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 35791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 35801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Slow case: call runtime. 35821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&slow); 3583257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Counters* counters = masm->isolate()->counters(); 3584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->keyed_store_external_array_slow(), 1); 3585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 35861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------- S t a t e ------------- 35871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- eax : value 35881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- ecx : key 35891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- edx : receiver 35901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- esp[0] : return address 35911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 35921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow(); 3594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(ic, RelocInfo::CODE_TARGET); 3595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- eax : value 3598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ecx : key 3599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- edx : receiver 3600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- esp[0] : return address 3601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 3604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> miss_ic = 3605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 3606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(miss_ic, RelocInfo::CODE_TARGET); 3607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) { 3611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- eax : key 3613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- edx : receiver 3614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- esp[0] : return address 3615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss_force_generic; 3617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 3619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 3620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3621257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is a smi. 36223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(eax, &miss_force_generic); 3623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the elements array. 3625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); 3626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AssertFastElements(ecx); 3627257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is within bounds. 3629257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); 3630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above_equal, &miss_force_generic); 3631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the result and make sure it's not the hole. 3633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(ebx, Operand(ecx, eax, times_2, 3634257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FixedArray::kHeaderSize - kHeapObjectTag)); 3635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(ebx, masm->isolate()->factory()->the_hole_value()); 3636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &miss_force_generic); 3637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(eax, ebx); 3638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ret(0); 3639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 3641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> miss_ic = 3642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 3643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(miss_ic, RelocInfo::CODE_TARGET); 3644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 36473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastDoubleElement( 36483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MacroAssembler* masm) { 36493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------- S t a t e ------------- 36503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- eax : key 36513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- edx : receiver 36523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- esp[0] : return address 36533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------------------------------- 36543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label miss_force_generic, slow_allocate_heapnumber; 36553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 36563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 36573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // have been verified by the caller to not be a smi. 36583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 36593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is a smi. 36603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(eax, &miss_force_generic); 36613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 36623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Get the elements array. 36633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); 36643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ AssertFastElements(ecx); 36653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 36663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is within bounds. 36673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp(eax, FieldOperand(ecx, FixedDoubleArray::kLengthOffset)); 36683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(above_equal, &miss_force_generic); 36693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 36703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check for the hole 36713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32); 36723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp(FieldOperand(ecx, eax, times_4, offset), Immediate(kHoleNanUpper32)); 36733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(equal, &miss_force_generic); 36743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 36753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Always allocate a heap number for the result. 36763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (CpuFeatures::IsSupported(SSE2)) { 36773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CpuFeatures::Scope use_sse2(SSE2); 36783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movdbl(xmm0, FieldOperand(ecx, eax, times_4, 36793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FixedDoubleArray::kHeaderSize)); 36803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 36813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ fld_d(FieldOperand(ecx, eax, times_4, FixedDoubleArray::kHeaderSize)); 36823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 36833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ AllocateHeapNumber(ecx, ebx, edi, &slow_allocate_heapnumber); 36843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Set the value. 36853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (CpuFeatures::IsSupported(SSE2)) { 36863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CpuFeatures::Scope use_sse2(SSE2); 36873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movdbl(FieldOperand(ecx, HeapNumber::kValueOffset), xmm0); 36883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 36893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ fstp_d(FieldOperand(ecx, HeapNumber::kValueOffset)); 36903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 36913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(eax, ecx); 36923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ret(0); 36933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 36943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&slow_allocate_heapnumber); 36953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // A value was pushed on the floating point stack before the allocation, if 36963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // the allocation fails it needs to be removed. 36973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!CpuFeatures::IsSupported(SSE2)) { 3698592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ fstp(0); 36993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 37003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> slow_ic = 37013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_Slow(); 37023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(slow_ic, RelocInfo::CODE_TARGET); 37033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&miss_force_generic); 37053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> miss_ic = 37063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 37073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(miss_ic, RelocInfo::CODE_TARGET); 37083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 37093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 3711592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastElement( 3712592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch MacroAssembler* masm, 3713592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch bool is_js_array, 3714592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ElementsKind elements_kind) { 3715257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 37163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- eax : value 37173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- ecx : key 3718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- edx : receiver 3719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- esp[0] : return address 3720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3721592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Label miss_force_generic, transition_elements_kind; 3722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 3724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 3725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is a smi. 37273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(ecx, &miss_force_generic); 37281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the elements array and make sure it is a fast element array, not 'cow'. 3730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 3731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(FieldOperand(edi, HeapObject::kMapOffset), 3732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Immediate(masm->isolate()->factory()->fixed_array_map())); 3733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss_force_generic); 3734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (is_js_array) { 3736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is within bounds. 3737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis. 3738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above_equal, &miss_force_generic); 3739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is within bounds. 3741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis. 3742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above_equal, &miss_force_generic); 3743257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3744257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3745592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { 3746592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ JumpIfNotSmi(eax, &transition_elements_kind); 3747592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // ecx is a smi, use times_half_pointer_size instead of 3748592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // times_pointer_size 3749592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(FieldOperand(edi, 3750592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ecx, 3751592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch times_half_pointer_size, 3752592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch FixedArray::kHeaderSize), eax); 3753592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } else { 3754592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT(elements_kind == FAST_ELEMENTS); 3755592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Do the store and update the write barrier. 3756592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // ecx is a smi, use times_half_pointer_size instead of 3757592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // times_pointer_size 3758592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ lea(ecx, FieldOperand(edi, 3759592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ecx, 3760592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch times_half_pointer_size, 3761592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch FixedArray::kHeaderSize)); 3762592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(Operand(ecx, 0), eax); 3763592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Make sure to preserve the value in register eax. 3764592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(edx, eax); 3765592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ RecordWrite(edi, ecx, edx, kDontSaveFPRegs); 3766592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 3767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Done. 3769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ret(0); 37701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Handle store cache miss, replacing the ic with the generic stub. 3772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 3773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic_force_generic = 3774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 3775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); 3776592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 3777592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Handle transition to other elements kinds without using the generic stub. 3778592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(&transition_elements_kind); 3779592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); 3780592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ jmp(ic_miss, RelocInfo::CODE_TARGET); 37811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 37821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( 37853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MacroAssembler* masm, 37863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool is_js_array) { 37873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------- S t a t e ------------- 37883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- eax : value 37893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- ecx : key 37903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- edx : receiver 37913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- esp[0] : return address 37923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------------------------------- 3793592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Label miss_force_generic, transition_elements_kind; 37943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 37963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // have been verified by the caller to not be a smi. 37973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is a smi. 37993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(ecx, &miss_force_generic); 38003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 38013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Get the elements array. 38023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 38033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ AssertFastElements(edi); 38043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 38053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (is_js_array) { 38063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is within bounds. 38073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis. 38083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 38093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is within bounds. 38103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis. 38113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 38123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(above_equal, &miss_force_generic); 38133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 3814592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ StoreNumberToDoubleElements(eax, 3815592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch edi, 3816592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ecx, 3817592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch edx, 3818592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch xmm0, 3819592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch &transition_elements_kind, 3820592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch true); 38213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ret(0); 38223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 38233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Handle store cache miss, replacing the ic with the generic stub. 38243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&miss_force_generic); 38253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> ic_force_generic = 38263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 38273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); 3828592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 3829592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Handle transition to other elements kinds without using the generic stub. 3830592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(&transition_elements_kind); 3831592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); 3832592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ jmp(ic_miss, RelocInfo::CODE_TARGET); 38333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 38343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 38353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 3836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 3837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 3839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_IA32 3841