stub-cache-ia32.cc revision 3ef787dbeca8a5fb1086949cda830dccee07bfbd
13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 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, 473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver, 483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Number of the cache entry pointer-size scaled. 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register offset, 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register extra) { 5144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference key_offset(isolate->stub_cache()->key_reference(table)); 5244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference value_offset(isolate->stub_cache()->value_reference(table)); 533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference map_offset(isolate->stub_cache()->map_reference(table)); 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Multiply by 3 because there are 3 fields per entry (name, code, map). 583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lea(offset, Operand(offset, offset, times_2, 0)); 593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (extra.is_valid()) { 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the code entry from the cache. 623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(extra, Operand::StaticArray(offset, times_1, value_offset)); 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the key in the entry matches the name. 653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(name, Operand::StaticArray(offset, times_1, key_offset)); 663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &miss); 673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check the map matches. 693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(offset, Operand::StaticArray(offset, times_1, map_offset)); 703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(offset, FieldOperand(receiver, HeapObject::kMapOffset)); 71257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the flags match what we're looking for. 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(offset, FieldOperand(extra, Code::kFlagsOffset)); 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(offset, ~Code::kFlagsNotUsedInLookup); 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(offset, flags); 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss); 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG 803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) { 813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&miss); 823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) { 833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&miss); 843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif 863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the first instruction in the code stub. 883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(extra, Immediate(Code::kHeaderSize - kHeapObjectTag)); 893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(extra); 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save the offset on the stack. 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(offset); 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the key in the entry matches the name. 973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(name, Operand::StaticArray(offset, times_1, key_offset)); 983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &miss); 993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check the map matches. 1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(offset, Operand::StaticArray(offset, times_1, map_offset)); 1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(offset, FieldOperand(receiver, HeapObject::kMapOffset)); 103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Restore offset register. 1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(offset, Operand(esp, 0)); 1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the code entry from the cache. 1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(offset, Operand::StaticArray(offset, times_1, value_offset)); 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the flags match what we're looking for. 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(offset, FieldOperand(offset, Code::kFlagsOffset)); 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(offset, ~Code::kFlagsNotUsedInLookup); 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(offset, flags); 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss); 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG 1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) { 1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&miss); 1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) { 1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&miss); 1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif 1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore offset and re-load code entry from cache. 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(offset); 1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(offset, Operand::StaticArray(offset, times_1, value_offset)); 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the first instruction in the code stub. 1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(offset, Immediate(Code::kHeaderSize - kHeapObjectTag)); 1313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(offset); 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pop at miss. 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(offset); 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1408defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Helper function used to check that the dictionary doesn't contain 1418defd9ff6930b4e24729971a61cf7469daf119beSteve Block// the property. This function may return false negatives, so miss_label 1428defd9ff6930b4e24729971a61cf7469daf119beSteve Block// must always call a backup property check that is complete. 1438defd9ff6930b4e24729971a61cf7469daf119beSteve Block// This function is safe to call if the receiver has fast properties. 1448defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Name must be a symbol and receiver must be a heap object. 1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateDictionaryNegativeLookup(MacroAssembler* masm, 1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss_label, 1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver, 1483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 1493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register r0, 1503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register r1) { 1518defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(name->IsSymbol()); 15244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = masm->isolate()->counters(); 15344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->negative_lookups(), 1); 15444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->negative_lookups_miss(), 1); 1558defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1568defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); 1578defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1588defd9ff6930b4e24729971a61cf7469daf119beSteve Block const int kInterceptorOrAccessCheckNeededMask = 1598defd9ff6930b4e24729971a61cf7469daf119beSteve Block (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); 1603bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1618defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Bail out if the receiver has a named interceptor or requires access checks. 1623bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ test_b(FieldOperand(r0, Map::kBitFieldOffset), 1633bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch kInterceptorOrAccessCheckNeededMask); 164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, miss_label); 1658defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Check that receiver is a JSObject. 1673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpInstanceType(r0, FIRST_SPEC_OBJECT_TYPE); 168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(below, miss_label); 1698defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1708defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Load properties array. 1718defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register properties = r0; 1728defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); 1738defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1748defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Check that the properties array is a dictionary. 1758defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ cmp(FieldOperand(properties, HeapObject::kMapOffset), 17644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Immediate(masm->isolate()->factory()->hash_table_map())); 1778defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(not_equal, miss_label); 1788defd9ff6930b4e24729971a61cf7469daf119beSteve Block 179257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringDictionaryLookupStub::GenerateNegativeLookup(masm, 1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch miss_label, 1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &done, 1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch properties, 1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, 1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r1); 1868defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ bind(&done); 18744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->negative_lookups_miss(), 1); 1888defd9ff6930b4e24729971a61cf7469daf119beSteve Block} 1898defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1908defd9ff6930b4e24729971a61cf7469daf119beSteve Block 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCache::GenerateProbe(MacroAssembler* masm, 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Flags flags, 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register name, 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 1963e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu Register extra, 1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register extra2, 1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register extra3) { 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Assert that code is valid. The multiplying code relies on the entry size 2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // being 12. 2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(sizeof(Entry) == 12); 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Assert the flags do not name a specific type. 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(Code::ExtractTypeFromFlags(flags) == 0); 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Assert that there are no register conflicts. 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!scratch.is(receiver)); 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!scratch.is(name)); 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!extra.is(receiver)); 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!extra.is(name)); 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!extra.is(scratch)); 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Assert scratch and extra registers are valid, and extra2/3 are unused. 2163e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(!scratch.is(no_reg)); 2173e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(extra2.is(no_reg)); 2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(extra3.is(no_reg)); 2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register offset = scratch; 2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch = no_reg; 2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Counters* counters = masm->isolate()->counters(); 2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1); 2253e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 2273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(receiver, &miss); 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the map of the receiver and compute the hash. 2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(offset, FieldOperand(name, String::kHashFieldOffset)); 2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(offset, FieldOperand(receiver, HeapObject::kMapOffset)); 2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ xor_(offset, flags); 2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We mask out the last two bits because they are not part of the hash and 2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // they are always 01 for maps. Also in the two 'and' instructions below. 2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ and_(offset, (kPrimaryTableSize - 1) << kHeapObjectTagSize); 2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ProbeTable expects the offset to be pointer scaled, which it is, because 2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the heap object tag size is 2 and the pointer size log 2 is also 2. 2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(kHeapObjectTagSize == kPointerSizeLog2); 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the primary table. 2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ProbeTable(isolate(), masm, flags, kPrimary, name, receiver, offset, extra); 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Primary miss: Compute hash for secondary probe. 2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(offset, FieldOperand(name, String::kHashFieldOffset)); 2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(offset, FieldOperand(receiver, HeapObject::kMapOffset)); 2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ xor_(offset, flags); 2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ and_(offset, (kPrimaryTableSize - 1) << kHeapObjectTagSize); 2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(offset, name); 2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(offset, Immediate(flags)); 2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ and_(offset, (kSecondaryTableSize - 1) << kHeapObjectTagSize); 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the secondary table. 2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ProbeTable( 2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate(), masm, flags, kSecondary, name, receiver, offset, extra); 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cache miss: Fall-through and let caller handle the miss by 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // entering the runtime system. 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1); 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index, 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register prototype) { 26680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadGlobalFunction(index, prototype); 26780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadGlobalFunctionInitialMap(prototype, prototype); 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the prototype from the initial map. 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( 2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler* masm, 2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int index, 2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register prototype, 2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 2780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Check we're still in the same context. 2790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ cmp(Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)), 28044f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm->isolate()->global()); 2810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ j(not_equal, miss); 2827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Get the global function with the given index. 2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function( 2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JSFunction::cast(masm->isolate()->global_context()->get(index))); 2857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Load its initial map. The global functions all have initial maps. 2867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Set(prototype, Immediate(Handle<Map>(function->initial_map()))); 2877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Load the prototype from the initial map. 2887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); 2897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 2907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss_label) { 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 2973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(receiver, miss_label); 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is a JS array. 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); 301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, miss_label); 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load length directly from the JS array. 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset)); 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate code to check if an object is a string. If the object is 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// a string, the map's instance type is left in the scratch register. 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GenerateStringCheck(MacroAssembler* masm, 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* smi, 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* non_string_object) { 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object isn't a smi. 3173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(receiver, smi); 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is a string. 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 32269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kNotStringTag != 0); 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(scratch, Immediate(kNotStringTag)); 324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, non_string_object); 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 330402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register scratch1, 331402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register scratch2, 3321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* miss, 3331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool support_wrappers) { 334402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label check_wrapper; 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the object is a string leaving the instance type in the 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch register. 3381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block GenerateStringCheck(masm, receiver, scratch1, miss, 3391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block support_wrappers ? &check_wrapper : miss); 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 341d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load length from the string and convert to a smi. 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, FieldOperand(receiver, String::kLengthOffset)); 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (support_wrappers) { 3461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check if the object is a JSValue wrapper. 3471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&check_wrapper); 3481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmp(scratch1, JS_VALUE_TYPE); 349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, miss); 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check if the wrapped value is a string and load the length 3521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // directly if it is. 3531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset)); 3541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block GenerateStringCheck(masm, scratch2, scratch1, miss, miss); 3551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(eax, FieldOperand(scratch2, String::kLengthOffset)); 3561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 3571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss_label) { 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); 3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(eax, scratch1); 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Load a fast property out of a holder object (src). In-object properties 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// are loaded directly otherwise the property is loaded from the properties 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// fixed array. 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, 3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register dst, 3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register src, 3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int index) { 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust for the number of properties stored in the holder. 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block index -= holder->map()->inobject_properties(); 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (index < 0) { 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the property straight out of the holder. 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = holder->map()->instance_size() + (index * kPointerSize); 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(dst, FieldOperand(src, offset)); 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the offset into the properties array. 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = index * kPointerSize + FixedArray::kHeaderSize; 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(dst, FieldOperand(dst, offset)); 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 395402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescustatic void PushInterceptorArguments(MacroAssembler* masm, 396402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register receiver, 397402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register holder, 398402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register name, 3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder_obj) { 400402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(name); 4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); 4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); 4036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch = name; 4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(scratch, Immediate(interceptor)); 4056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(scratch); 406402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(receiver); 4076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(holder); 4086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(FieldOperand(scratch, InterceptorInfo::kDataOffset)); 409402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 410402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 411402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void CompileCallLoadPropertyWithInterceptor( 4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler* masm, 4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver, 4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register holder, 4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register name, 4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder_obj) { 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PushInterceptorArguments(masm, receiver, holder, name, holder_obj); 419402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CallExternalReference( 42044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), 42144f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm->isolate()), 42244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 5); 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 42690bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner// Number of pointers to be reserved on stack for fast API call. 42790bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brennerstatic const int kFastApiCallArguments = 3; 42890bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner 42990bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner 4308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang// Reserves space for the extra arguments to API function in the 431402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// caller's frame. 432402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// 433402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// These arguments are set by CheckPrototypes and GenerateFastApiCall. 434402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescustatic void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { 435402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------- S t a t e ------------- 436402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- esp[0] : return address 437402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- esp[4] : last argument in the internal frame of the caller 438402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------------------------------- 439402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(scratch); 44090bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner for (int i = 0; i < kFastApiCallArguments; i++) { 44190bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner __ push(Immediate(Smi::FromInt(0))); 44290bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner } 443402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(scratch); 444402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 445402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 446402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 447402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// Undoes the effects of ReserveSpaceForFastApiCall. 448402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescustatic void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { 449402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------- S t a t e ------------- 45090bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner // -- esp[0] : return address. 45190bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner // -- esp[4] : last fast api call extra argument. 452402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- ... 45390bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner // -- esp[kFastApiCallArguments * 4] : first fast api call extra argument. 45490bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner // -- esp[kFastApiCallArguments * 4 + 4] : last argument in the internal 45590bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner // frame. 456402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------------------------------- 457402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(scratch); 4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(esp, Immediate(kPointerSize * kFastApiCallArguments)); 459402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(scratch); 460402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 461402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 462402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 4638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang// Generates call to API function. 4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateFastApiCall(MacroAssembler* masm, 4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const CallOptimization& optimization, 4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int argc) { 467402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------- S t a t e ------------- 468402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- esp[0] : return address 469402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- esp[4] : object passing the type check 470402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // (last fast api call extra argument, 471402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // set by CheckPrototypes) 47290bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner // -- esp[8] : api function 473402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // (first fast api call extra argument) 47490bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner // -- esp[12] : api call data 47590bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner // -- esp[16] : last argument 476402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- ... 47790bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner // -- esp[(argc + 3) * 4] : first argument 47890bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner // -- esp[(argc + 4) * 4] : receiver 479402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------------------------------- 480402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Get the function and setup the context. 4813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function = optimization.constant_function(); 4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(edi, function); 483402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 484402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 4858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Pass the additional arguments. 48690bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner __ mov(Operand(esp, 2 * kPointerSize), edi); 4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> call_data(api_call_info->data()); 4893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (masm->isolate()->heap()->InNewSpace(*call_data)) { 4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ecx, api_call_info); 491402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset)); 49290bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner __ mov(Operand(esp, 3 * kPointerSize), ebx); 493402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(Operand(esp, 3 * kPointerSize), Immediate(call_data)); 495402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 496402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 4978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Prepare arguments. 49890bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner __ lea(eax, Operand(esp, 3 * kPointerSize)); 499402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 5008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const int kApiArgc = 1; // API function gets reference to the v8::Arguments. 50190bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner 5028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Allocate the v8::Arguments structure in the arguments' space since 5038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // it's not controlled by GC. 5048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const int kApiStackSpace = 4; 5058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 5063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ PrepareCallApiFunction(kApiArgc + kApiStackSpace); 5078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 5088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(ApiParameterOperand(1), eax); // v8::Arguments::implicit_args_. 5093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(eax, Immediate(argc * kPointerSize)); 5108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(ApiParameterOperand(2), eax); // v8::Arguments::values_. 5118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Set(ApiParameterOperand(3), Immediate(argc)); // v8::Arguments::length_. 5128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // v8::Arguments::is_construct_call_. 5138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Set(ApiParameterOperand(4), Immediate(0)); 5148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 5158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // v8::InvocationCallback's argument. 5168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ lea(eax, ApiParameterOperand(1)); 5178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(ApiParameterOperand(0), eax); 51890bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner 5193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Function address is a foreign pointer outside V8's heap. 5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Address function_address = v8::ToCData<Address>(api_call_info->callback()); 5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallApiFunctionAndReturn(function_address, 5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch argc + kFastApiCallArguments + 1); 523402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 524402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 525402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CallInterceptorCompiler BASE_EMBEDDED { 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 528402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu CallInterceptorCompiler(StubCompiler* stub_compiler, 529402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu const ParameterCount& arguments, 530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register name, 5313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Code::ExtraICState extra_state) 532402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu : stub_compiler_(stub_compiler), 533402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu arguments_(arguments), 534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch name_(name), 5353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch extra_state_(extra_state) {} 5363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void Compile(MacroAssembler* masm, 5383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 5393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 5403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 5413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult* lookup, 5423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver, 5433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 5443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch2, 5453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch3, 5463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 547402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(holder->HasNamedInterceptor()); 548402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); 549402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 550402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Check that the receiver isn't a smi. 5513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(receiver, miss); 552402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 553402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu CallOptimization optimization(lookup); 5546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (optimization.is_constant_call()) { 5553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3, 5563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch holder, lookup, name, optimization, miss); 557402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 5583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3, 5593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, holder, miss); 560402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 561402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 563402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu private: 5643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CompileCacheable(MacroAssembler* masm, 5653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 5663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver, 5673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 5683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch2, 5693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch3, 5703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> interceptor_holder, 5713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult* lookup, 5723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 5733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const CallOptimization& optimization, 5743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss_label) { 575402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(optimization.is_constant_call()); 576402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(!lookup->holder()->IsGlobalObject()); 577402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 578402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int depth1 = kInvalidProtoDepth; 579402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int depth2 = kInvalidProtoDepth; 580402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu bool can_do_fast_api_call = false; 581402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (optimization.is_simple_api_call() && 582402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu !lookup->holder()->IsGlobalObject()) { 5833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch depth1 = optimization.GetPrototypeDepthOfExpectedType( 5843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch object, interceptor_holder); 585402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (depth1 == kInvalidProtoDepth) { 5863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch depth2 = optimization.GetPrototypeDepthOfExpectedType( 5873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch interceptor_holder, Handle<JSObject>(lookup->holder())); 588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 5893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch can_do_fast_api_call = 5903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth; 591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 59344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = masm->isolate()->counters(); 59444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_const_interceptor(), 1); 595402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 596402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (can_do_fast_api_call) { 59744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1); 598402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ReserveSpaceForFastApiCall(masm, scratch1); 599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check that the maps from receiver to interceptor's holder 602f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // haven't changed and thus we can invoke interceptor. 603402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label miss_cleanup; 604402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; 605402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register holder = 6063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, 6073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, scratch2, scratch3, 6083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, depth1, miss); 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 610f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invoke an interceptor and if it provides a value, 611f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // branch to |regular_invoke|. 612402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label regular_invoke; 613f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke LoadWithInterceptor(masm, receiver, holder, interceptor_holder, 614f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ®ular_invoke); 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 616f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Interceptor returned nothing for this property. Try to use cached 617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // constant function. 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 619f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check that the maps from interceptor's holder to constant function's 620f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // holder haven't changed and thus we can use cached constant function. 6213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (*interceptor_holder != lookup->holder()) { 6227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch stub_compiler_->CheckPrototypes(interceptor_holder, receiver, 6233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(lookup->holder()), 6243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, scratch2, scratch3, 6253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, depth2, miss); 6267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 6277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // CheckPrototypes has a side effect of fetching a 'holder' 6287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // for API (object which is instanceof for the signature). It's 6297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // safe to omit it here, as if present, it should be fetched 6307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // by the previous CheckPrototypes. 6317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(depth2 == kInvalidProtoDepth); 6327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 634f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invoke function. 635402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (can_do_fast_api_call) { 6363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateFastApiCall(masm, optimization, arguments_.immediate()); 637402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 6383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 641402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ InvokeFunction(optimization.constant_function(), arguments_, 642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch JUMP_FUNCTION, NullCallWrapper(), call_kind); 643402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 645f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Deferred code for fast API call case---clean preallocated space. 646402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (can_do_fast_api_call) { 647402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ bind(&miss_cleanup); 648402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu FreeSpaceForFastApiCall(masm, scratch1); 649402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ jmp(miss_label); 650402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 652f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invoke a regular function. 653402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ bind(®ular_invoke); 654402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (can_do_fast_api_call) { 655402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu FreeSpaceForFastApiCall(masm, scratch1); 656402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CompileRegular(MacroAssembler* masm, 6603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 662402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register scratch1, 663402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register scratch2, 6643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 6653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 6663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> interceptor_holder, 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss_label) { 668402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register holder = 669f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, 6703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, scratch2, scratch3, 6713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, miss_label); 672402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 6733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 674e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save the name_ register across the call. 675e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(name_); 676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder); 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 679402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CallExternalReference( 68044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), 68144f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm->isolate()), 68244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 5); 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 684e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Restore the name_ register. 685e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(name_); 6863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Leave the internal frame. 688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 690402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void LoadWithInterceptor(MacroAssembler* masm, 691402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register receiver, 692402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register holder, 6933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder_obj, 694402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label* interceptor_succeeded) { 6953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 6963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 6973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(holder); // Save the holder. 6983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(name_); // Save the name. 6993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompileCallLoadPropertyWithInterceptor(masm, 7013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver, 7023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch holder, 7033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name_, 7043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch holder_obj); 7053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(name_); // Restore the name. 7073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(receiver); // Restore the holder. 7083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Leave the internal frame. 7093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 710402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 71144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(eax, masm->isolate()->factory()->no_interceptor_result_sentinel()); 712402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ j(not_equal, interceptor_succeeded); 713402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 714402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 715402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu StubCompiler* stub_compiler_; 716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& arguments_; 717e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register name_; 7183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Code::ExtraICState extra_state_; 719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { 723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); 7243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = (kind == Code::LOAD_IC) 7253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? masm->isolate()->builtins()->LoadIC_Miss() 7263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : masm->isolate()->builtins()->KeyedLoadIC_Miss(); 7273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(code, RelocInfo::CODE_TARGET); 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) { 7323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = 7333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 7343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(code, RelocInfo::CODE_TARGET); 735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 738402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// Both name_reg and receiver_reg are preserved on jumps to miss_label, 739402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// but may be destroyed if store is successful. 740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateStoreField(MacroAssembler* masm, 7413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index, 7433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> transition, 744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver_reg, 745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register name_reg, 746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss_label) { 748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the object hasn't changed. 7493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(receiver_reg, Handle<Map>(object->map()), 7503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch miss_label, DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); 751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform global security token check if needed. 753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsJSGlobalProxy()) { 754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); 755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stub never generated for non-global objects that require access 758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks. 759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform map transition for the receiver if necessary. 7623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) { 763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The properties must be extended before we can store the value. 764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We jump to a runtime call that extends the properties array. 765402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(scratch); // Return address. 766402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(receiver_reg); 7673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(Immediate(transition)); 768402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(eax); 769402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(scratch); 7706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference( 77144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), 77244f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm->isolate()), 77344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3, 77444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1); 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!transition.is_null()) { 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update the map of the object; no write barrier updating is 780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // needed because the map is never in new space. 781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset), 7823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(transition)); 783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust for the number of properties stored in the object. Even in the 786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // face of a transition we can use the old map here because the size of the 787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object and the number of in-object properties is not going to change. 788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block index -= object->map()->inobject_properties(); 789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (index < 0) { 791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the property straight into the object. 792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = object->map()->instance_size() + (index * kPointerSize); 793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(FieldOperand(receiver_reg, offset), eax); 794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update the write barrier for the array address. 796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pass the value being stored in the now unused name_reg. 7973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(name_reg, eax); 7983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(receiver_reg, 7993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch offset, 8003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name_reg, 8013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 8023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs); 803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Write to the properties array. 805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = index * kPointerSize + FixedArray::kHeaderSize; 806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the properties array (optimistically). 807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); 808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(FieldOperand(scratch, offset), eax); 809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update the write barrier for the array address. 811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pass the value being stored in the now unused name_reg. 8123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(name_reg, eax); 8133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(scratch, 8143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch offset, 8153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name_reg, 8163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver_reg, 8173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs); 818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the value (register eax). 821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Generate code to check that a global property cell is empty. Create 8266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// the property cell at compilation time if no cell exists for the 8276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// property. 8283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateCheckPropertyCell(MacroAssembler* masm, 8293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject> global, 8303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 8313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 8323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 8333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell = 8343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GlobalObject::EnsurePropertyCell(global, name); 8356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(cell->value()->IsTheHole()); 8363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Oddball> the_hole = masm->isolate()->factory()->the_hole_value(); 837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (Serializer::enabled()) { 8383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(scratch, Immediate(cell)); 839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), 8403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(the_hole)); 841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 8423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(Operand::Cell(cell), Immediate(the_hole)); 843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, miss); 8456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 8466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8488defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Calls GenerateCheckPropertyCell for each global object in the prototype chain 8498defd9ff6930b4e24729971a61cf7469daf119beSteve Block// from object to (but not including) holder. 8503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateCheckPropertyCells(MacroAssembler* masm, 8513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 8523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 8533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 8543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 8553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 8563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> current = object; 8573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch while (!current.is_identical_to(holder)) { 8588defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (current->IsGlobalObject()) { 8593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateCheckPropertyCell(masm, 8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject>::cast(current), 8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, 8623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 8633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch miss); 8648defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 8653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); 8668defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 8678defd9ff6930b4e24729971a61cf7469daf119beSteve Block} 8688defd9ff6930b4e24729971a61cf7469daf119beSteve Block 869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm()) 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8733ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochRegister StubCompiler::CheckPrototypes(Handle<JSObject> object, 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register object_reg, 8753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register holder_reg, 8773bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch1, 8783bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch2, 8793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 8808defd9ff6930b4e24729971a61cf7469daf119beSteve Block int save_at_depth, 8813bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* miss) { 8828defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Make sure there's no overlap between holder and object registers. 8833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 8843bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) 8853bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch && !scratch2.is(scratch1)); 88644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 8878defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Keep track of the current object in register reg. 8888defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register reg = object_reg; 8893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> current = object; 8908defd9ff6930b4e24729971a61cf7469daf119beSteve Block int depth = 0; 8918defd9ff6930b4e24729971a61cf7469daf119beSteve Block 8928defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (save_at_depth == depth) { 8938defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(Operand(esp, kPointerSize), reg); 8948defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8968defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Traverse the prototype chain and check the maps in the prototype chain for 8978defd9ff6930b4e24729971a61cf7469daf119beSteve Block // fast and global objects or do negative lookup for normal objects. 8983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch while (!current.is_identical_to(holder)) { 8993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ++depth; 9008defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9018defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Only global objects and objects that do not require access 9028defd9ff6930b4e24729971a61cf7469daf119beSteve Block // checks are allowed in stubs. 9038defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); 9048defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> prototype(JSObject::cast(current->GetPrototype())); 9068defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (!current->HasFastProperties() && 9078defd9ff6930b4e24729971a61cf7469daf119beSteve Block !current->IsJSGlobalObject() && 9088defd9ff6930b4e24729971a61cf7469daf119beSteve Block !current->IsJSGlobalProxy()) { 9098defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (!name->IsSymbol()) { 9103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name = factory()->LookupSymbol(name); 9118defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 9123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(current->property_dictionary()->FindEntry(*name) == 9138defd9ff6930b4e24729971a61cf7469daf119beSteve Block StringDictionary::kNotFound); 9148defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateDictionaryNegativeLookup(masm(), miss, reg, name, 9163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, scratch2); 917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 9183bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); 9193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch reg = holder_reg; // From now on the object will be in holder_reg. 9203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); 9213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 9223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool in_new_space = heap()->InNewSpace(*prototype); 9233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> current_map(current->map()); 9243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (in_new_space) { 9253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Save the map in scratch1 for later. 9263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); 9278defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 9283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK, 9293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ALLOW_ELEMENT_TRANSITION_MAPS); 9303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check access rights to the global object. This has to happen after 9323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the map check so that we know that the object is actually a global 9333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // object. 9348defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (current->IsJSGlobalProxy()) { 9353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckAccessGlobalProxy(reg, scratch2, miss); 9363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 9373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch reg = holder_reg; // From now on the object will be in holder_reg. 9383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (in_new_space) { 9403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The prototype is in new space; we cannot store a reference to it 9413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // in the code. Load it from the map. 9423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); 9433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 9443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The prototype is in old space; load it directly. 9453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(reg, prototype); 946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 9488defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9498defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (save_at_depth == depth) { 9508defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(Operand(esp, kPointerSize), reg); 9518defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 9528defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9538defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Go to the next object in the prototype chain. 9548defd9ff6930b4e24729971a61cf7469daf119beSteve Block current = prototype; 955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 9563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(current.is_identical_to(holder)); 9578defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9588defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Log the check depth. 95944f0eee88ff00398ff7f715fab053374d808c90dSteve Block LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); 9608defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9618defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Check the holder map. 9623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(reg, Handle<Map>(holder->map()), 9633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch miss, DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); 9648defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9658defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Perform security check for access to the global object. 9668defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); 9678defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (holder->IsJSGlobalProxy()) { 9683bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ CheckAccessGlobalProxy(reg, scratch1, miss); 9693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 9703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If we've skipped any global objects, it's not enough to verify that 9723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // their maps haven't changed. We also need to check that the property 9733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // cell for the property is still empty. 9743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); 975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 976402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Return the register containing the holder. 9778defd9ff6930b4e24729971a61cf7469daf119beSteve Block return reg; 978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadField(Handle<JSObject> object, 9823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 9863bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index, 9883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 9913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(receiver, miss); 992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the prototype chain. 9943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register reg = CheckPrototypes( 9953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch object, receiver, holder, scratch1, scratch2, scratch3, name, miss); 996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the value from the properties. 998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateFastPropertyLoad(masm(), eax, reg, holder, index); 999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadCallback(Handle<JSObject> object, 10043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 10053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver, 10063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register name_reg, 10073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 10083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch2, 10093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch3, 10103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback, 10113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 10123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 10143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(receiver, miss); 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 10173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register reg = CheckPrototypes(object, receiver, holder, scratch1, 10183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch2, scratch3, name, miss); 1019d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 10208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Insert additional parameters into the stack frame above return address. 10218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ASSERT(!scratch3.is(reg)); 10228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ pop(scratch3); // Get return address to place it below. 10238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(receiver); // receiver 10253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(scratch2, esp); 10268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ASSERT(!scratch2.is(reg)); 1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(reg); // holder 10289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Push data from AccessorInfo. 10293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (isolate()->heap()->InNewSpace(callback->data())) { 10303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(scratch1, Immediate(callback)); 10318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset)); 10329dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } else { 10333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(Immediate(Handle<Object>(callback->data()))); 10349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 10358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1036d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Save a pointer to where we pushed the arguments pointer. 10376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // This will be passed as the const AccessorInfo& to the C++ callback. 10388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(scratch2); 10398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 10408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(name_reg); // name 10418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(ebx, esp); // esp points to reference to name (handler). 10428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 10438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(scratch3); // Restore return address. 1044d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 10453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 3 elements array for v8::Arguments::values_, handler for name and pointer 10468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // to the values (it considered as smi in GC). 10478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const int kStackSpace = 5; 10488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const int kApiArgc = 2; 10498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 10503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ PrepareCallApiFunction(kApiArgc); 10518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(ApiParameterOperand(0), ebx); // name. 10523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(ebx, Immediate(kPointerSize)); 10538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(ApiParameterOperand(1), ebx); // arguments pointer. 10548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1055e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emitting a stub call may try to allocate (if the code is not 1056e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // already generated). Do not allow the assembler to perform a 1057e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // garbage collection but instead return the allocation failure 1058e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // object. 10593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Address getter_address = v8::ToCData<Address>(callback->getter()); 10603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallApiFunctionAndReturn(getter_address, kStackSpace); 1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadConstant(Handle<JSObject> object, 10653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 10693bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 10703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> value, 10713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 10743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(receiver, miss); 1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 10773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes( 10783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch object, receiver, holder, scratch1, scratch2, scratch3, name, miss); 1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the constant value. 10813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(eax, value); 1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object, 10873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> interceptor_holder, 1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupResult* lookup, 1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register name_reg, 1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 10933bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 10943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 10967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(interceptor_holder->HasNamedInterceptor()); 10977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); 10987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 10997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the receiver isn't a smi. 11003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(receiver, miss); 11017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // So far the most popular follow ups for interceptor loads are FIELD 11037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // and CALLBACKS, so inline only them, other cases may be added 11047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // later. 11057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch bool compile_followup_inline = false; 11063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (lookup->IsFound() && lookup->IsCacheable()) { 11077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (lookup->type() == FIELD) { 11087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch compile_followup_inline = true; 11097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else if (lookup->type() == CALLBACKS && 11103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lookup->GetCallbackObject()->IsAccessorInfo()) { 11113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch compile_followup_inline = 11123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL; 11137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 11147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 11157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (compile_followup_inline) { 11177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Compile the interceptor call, followed by inline code to load the 11187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // property from further up the prototype chain if the call fails. 11197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps haven't changed. 11207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, 11213bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch1, scratch2, scratch3, 11223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch name, miss); 11237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1)); 11247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Save necessary data before invoking an interceptor. 11267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Requires a frame to make GC aware of pushed pointers. 11273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 11283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope frame_scope(masm(), StackFrame::INTERNAL); 11297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { 11313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // CALLBACKS case needs a receiver to be passed into C++ callback. 11323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(receiver); 11333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 11343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(holder_reg); 11353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(name_reg); 1136592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 11373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Invoke an interceptor. Note: map checks from receiver to 11383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // interceptor's holder has been compiled before (see a caller 11393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // of this method.) 11403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompileCallLoadPropertyWithInterceptor(masm(), 11413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver, 11423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch holder_reg, 11433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name_reg, 11443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch interceptor_holder); 11453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 11463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if interceptor provided a value for property. If it's 11473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the case, return immediately. 11483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label interceptor_failed; 11493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(eax, factory()->no_interceptor_result_sentinel()); 11503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, &interceptor_failed); 11513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch frame_scope.GenerateLeaveFrame(); 11523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ret(0); 11537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&interceptor_failed); 11553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(name_reg); 11563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(holder_reg); 11573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { 11583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(receiver); 11593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 11603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 11613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Leave the internal frame. 11623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 116385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 11647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps from interceptor's holder to lookup's holder 11657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // haven't changed. And load lookup's holder into holder_reg. 11663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (*interceptor_holder != lookup->holder()) { 11677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch holder_reg = CheckPrototypes(interceptor_holder, 11687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch holder_reg, 11693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(lookup->holder()), 11707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch1, 11717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch2, 11723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch3, 11737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch name, 11747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch miss); 11757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 11767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (lookup->type() == FIELD) { 11787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // We found FIELD property in prototype chain of interceptor's holder. 11797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Retrieve a field from field's holder. 11807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateFastPropertyLoad(masm(), eax, holder_reg, 11813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(lookup->holder()), 11823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lookup->GetFieldIndex()); 11837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ ret(0); 11847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 11857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // We found CALLBACKS property in prototype chain of interceptor's 11867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // holder. 11877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(lookup->type() == CALLBACKS); 11883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback( 11893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AccessorInfo::cast(lookup->GetCallbackObject())); 11907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(callback->getter() != NULL); 11917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Tail call to runtime. 11937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Important invariant in CALLBACKS case: the code above must be 11947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // structured to never clobber |receiver| register. 11957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(scratch2); // return address 11967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(receiver); 11977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(holder_reg); 11983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(holder_reg, Immediate(callback)); 11997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset)); 12008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(holder_reg); 12017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(name_reg); 12027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(scratch2); // restore return address 12037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ExternalReference ref = 120544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kLoadCallbackProperty), 120644f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm()->isolate()); 12077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ TailCallExternalReference(ref, 5, 1); 12087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 12097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { // !compile_followup_inline 12107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Call the runtime system to load the interceptor. 12117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps haven't changed. 12127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register holder_reg = 12137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch CheckPrototypes(object, receiver, interceptor_holder, 12143bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch1, scratch2, scratch3, name, miss); 12157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(scratch2); // save old return address 12167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch PushInterceptorArguments(masm(), receiver, holder_reg, 12177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch name_reg, interceptor_holder); 12187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(scratch2); // restore old return address 12197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 122044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference ref = 122144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), 122244f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()); 12237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ TailCallExternalReference(ref, 5, 1); 12247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { 12297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (kind_ == Code::KEYED_CALL_IC) { 12303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(ecx, Immediate(name)); 1231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, miss); 12327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 12337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 12347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object, 12373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 12383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 123959151504615d929945dc59db37bf1166937748c6Steve Block Label* miss) { 124059151504615d929945dc59db37bf1166937748c6Steve Block ASSERT(holder->IsGlobalObject()); 124159151504615d929945dc59db37bf1166937748c6Steve Block 124259151504615d929945dc59db37bf1166937748c6Steve Block // Get the number of arguments. 124359151504615d929945dc59db37bf1166937748c6Steve Block const int argc = arguments().immediate(); 124459151504615d929945dc59db37bf1166937748c6Steve Block 124559151504615d929945dc59db37bf1166937748c6Steve Block // Get the receiver from the stack. 124659151504615d929945dc59db37bf1166937748c6Steve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 124759151504615d929945dc59db37bf1166937748c6Steve Block 124859151504615d929945dc59db37bf1166937748c6Steve Block 124959151504615d929945dc59db37bf1166937748c6Steve Block // Check that the maps haven't changed. 12503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(edx, miss); 125159151504615d929945dc59db37bf1166937748c6Steve Block CheckPrototypes(object, edx, holder, ebx, eax, edi, name, miss); 125259151504615d929945dc59db37bf1166937748c6Steve Block} 125359151504615d929945dc59db37bf1166937748c6Steve Block 125459151504615d929945dc59db37bf1166937748c6Steve Block 12553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateLoadFunctionFromCell( 12563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 12573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 12583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 125959151504615d929945dc59db37bf1166937748c6Steve Block // Get the value from the cell. 1260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (Serializer::enabled()) { 12613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(edi, Immediate(cell)); 1262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); 1263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 12643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(edi, Operand::Cell(cell)); 1265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 126659151504615d929945dc59db37bf1166937748c6Steve Block 126759151504615d929945dc59db37bf1166937748c6Steve Block // Check that the cell contains the same function. 12683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (isolate()->heap()->InNewSpace(*function)) { 126959151504615d929945dc59db37bf1166937748c6Steve Block // We can't embed a pointer to a function in new space so we have 127059151504615d929945dc59db37bf1166937748c6Steve Block // to verify that the shared function info is unchanged. This has 127159151504615d929945dc59db37bf1166937748c6Steve Block // the nice side effect that multiple closures based on the same 127259151504615d929945dc59db37bf1166937748c6Steve Block // function can all use this call IC. Before we load through the 127359151504615d929945dc59db37bf1166937748c6Steve Block // function, we have to verify that it still is a function. 12743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edi, miss); 127559151504615d929945dc59db37bf1166937748c6Steve Block __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); 1276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, miss); 127759151504615d929945dc59db37bf1166937748c6Steve Block 127859151504615d929945dc59db37bf1166937748c6Steve Block // Check the shared function info. Make sure it hasn't changed. 127959151504615d929945dc59db37bf1166937748c6Steve Block __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), 128059151504615d929945dc59db37bf1166937748c6Steve Block Immediate(Handle<SharedFunctionInfo>(function->shared()))); 128159151504615d929945dc59db37bf1166937748c6Steve Block } else { 12823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(edi, Immediate(function)); 128359151504615d929945dc59db37bf1166937748c6Steve Block } 12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, miss); 128559151504615d929945dc59db37bf1166937748c6Steve Block} 128659151504615d929945dc59db37bf1166937748c6Steve Block 128759151504615d929945dc59db37bf1166937748c6Steve Block 12883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateMissBranch() { 12893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = 129044f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), 1291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch kind_, 12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch extra_state_); 12933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(code, RelocInfo::CODE_TARGET); 12947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 12957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12973ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, 12983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 12993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int index, 13003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 1303e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 1304e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 1306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateNameCheck(name, &miss); 13117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver from the stack. 1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 13173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &miss); 1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do the right check and compute the holder register. 13203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register reg = CheckPrototypes(object, edx, holder, ebx, eax, edi, 13213bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch name, &miss); 1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateFastPropertyLoad(masm(), edi, reg, holder, index); 1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the function really is a function. 13263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edi, &miss); 1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); 1328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack with the global proxy if 1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // necessary. 1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsGlobalObject()) { 1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the function. 13383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 1339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 1340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 1341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, 1342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), call_kind); 1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 13463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(FIELD, name); 1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13533ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPushCall( 13543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 13553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 13563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 13573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 13583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 13596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 13606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : name 13616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[0] : return address 13626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[(argc - n) * 4] : arg[n] (zero-based) 13636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ... 13646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[(argc + 1) * 4] : receiver 13656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 13666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // If object is not an array, bail out to regular call. 13683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSArray() || !cell.is_null()) { 13693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Handle<Code>::null(); 137044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 13716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss; 13736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateNameCheck(name, &miss); 13757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the receiver from the stack. 13776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int argc = arguments().immediate(); 13786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 13796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the receiver isn't a smi. 13813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &miss); 13826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, 13843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 13856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (argc == 0) { 13876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Noop, return the length. 13886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); 13896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret((argc + 1) * kPointerSize); 13906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 1391756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label call_builtin; 1392756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 13933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (argc == 1) { // Otherwise fall through to call builtin. 13943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label attempt_to_grow_elements, with_write_barrier; 13956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the elements array of the object. 13973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(edi, FieldOperand(edx, JSArray::kElementsOffset)); 13985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 13993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that the elements are in fast mode and writable. 14003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(FieldOperand(edi, HeapObject::kMapOffset), 14013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(factory()->fixed_array_map())); 14023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &call_builtin); 14035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 14046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the array's length into eax and calculate new length. 14056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); 14066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block STATIC_ASSERT(kSmiTagSize == 1); 14076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block STATIC_ASSERT(kSmiTag == 0); 14083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(eax, Immediate(Smi::FromInt(argc))); 14096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the elements' length into ecx. 14113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); 14126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check if we could survive without allocation. 14143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(eax, ecx); 14156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(greater, &attempt_to_grow_elements); 14166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if value is a smi. 14183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ecx, Operand(esp, argc * kPointerSize)); 14193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfNotSmi(ecx, &with_write_barrier); 14203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Save new length. 14226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); 14236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the value. 14253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(edi, 14263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch eax, 14273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch times_half_pointer_size, 14283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArray::kHeaderSize - argc * kPointerSize), 14293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ecx); 143085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 14316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret((argc + 1) * kPointerSize); 14326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&with_write_barrier); 14346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); 14363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) { 14383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label fast_object, not_fast_object; 14393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastObjectElements(ebx, ¬_fast_object, Label::kNear); 14403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&fast_object); 14413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // In case of fast smi-only, convert to fast object, otherwise bail out. 14423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(¬_fast_object); 14433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastSmiOnlyElements(ebx, &call_builtin); 14443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // edi: elements array 14453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // edx: receiver 14463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ebx: map 14473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS, 14483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FAST_ELEMENTS, 14493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ebx, 14503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch edi, 14513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &call_builtin); 14523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsTransitionGenerator::GenerateSmiOnlyToObject(masm()); 14533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Restore edi. 14543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(edi, FieldOperand(edx, JSArray::kElementsOffset)); 14553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&fast_object); 14563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 14573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastObjectElements(ebx, &call_builtin); 14583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 14593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Save new length. 14613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); 14623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the value. 14643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lea(edx, FieldOperand(edi, 14653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch eax, times_half_pointer_size, 14663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArray::kHeaderSize - argc * kPointerSize)); 14673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(Operand(edx, 0), ecx); 14683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWrite(edi, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, 14703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_SMI_CHECK); 14716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret((argc + 1) * kPointerSize); 14736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&attempt_to_grow_elements); 14755913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!FLAG_inline_new) { 14765913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck __ jmp(&call_builtin); 14775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 14785913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 14793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ebx, Operand(esp, argc * kPointerSize)); 14803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Growing elements that are SMI-only requires special handling in case 14813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the new element is non-Smi. For now, delegate to the builtin. 14823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label no_fast_elements_check; 14833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(ebx, &no_fast_elements_check); 14843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 14853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastObjectElements(ecx, &call_builtin, Label::kFar); 14863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&no_fast_elements_check); 14873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We could be lucky and the elements array could be at the top of 14893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // new-space. In this case we can just grow it in place by moving the 14903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // allocation pointer up. 14913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference new_space_allocation_top = 149344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::new_space_allocation_top_address(isolate()); 14946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference new_space_allocation_limit = 149544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::new_space_allocation_limit_address(isolate()); 14966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kAllocationDelta = 4; 14986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Load top. 14996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ecx, Operand::StaticVariable(new_space_allocation_top)); 15006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check if it's the end of elements. 15023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lea(edx, FieldOperand(edi, 15036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block eax, times_half_pointer_size, 15046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FixedArray::kHeaderSize - argc * kPointerSize)); 15053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(edx, ecx); 15066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_equal, &call_builtin); 15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(ecx, Immediate(kAllocationDelta * kPointerSize)); 15086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(ecx, Operand::StaticVariable(new_space_allocation_limit)); 15096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(above, &call_builtin); 15106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // We fit and could grow elements. 15126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(Operand::StaticVariable(new_space_allocation_top), ecx); 15136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Push the argument... 15153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(Operand(edx, 0), ebx); 15166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ... and fill the rest with holes. 15176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (int i = 1; i < kAllocationDelta; i++) { 15186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(Operand(edx, i * kPointerSize), 151944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Immediate(factory()->the_hole_value())); 15206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 15216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We know the elements array is in new space so we don't need the 15233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // remembered set, but we just pushed a value onto it so we may have to 15243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // tell the incremental marker to rescan the object that we just grew. We 15253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // don't need to worry about the holes because they are in old space and 15263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // already marked black. 15273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWrite(edi, edx, ebx, kDontSaveFPRegs, OMIT_REMEMBERED_SET); 15283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Restore receiver to edx as finish sequence assumes it's here. 15306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 15316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Increment element's and array's sizes. 15333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(FieldOperand(edi, FixedArray::kLengthOffset), 15347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Immediate(Smi::FromInt(kAllocationDelta))); 15353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // NOTE: This only happen in new-space, where we don't 15373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // care about the black-byte-count on pages. Otherwise we should 15383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // update that too if the object is black. 15393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); 15416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret((argc + 1) * kPointerSize); 15436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 15446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1545756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ bind(&call_builtin); 154644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ TailCallExternalReference( 154744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(Builtins::c_ArrayPush, isolate()), 154844f0eee88ff00398ff7f715fab053374d808c90dSteve Block argc + 1, 154944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1); 15506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 15516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss); 15533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 15546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return the generated code. 155625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen return GetCode(function); 15576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 15586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15603ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPopCall( 15613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 15623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 15633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 15643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 15653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 15666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 15676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : name 15686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[0] : return address 15696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[(argc - n) * 4] : arg[n] (zero-based) 15706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ... 15716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[(argc + 1) * 4] : receiver 15726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 15736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // If object is not an array, bail out to regular call. 15753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSArray() || !cell.is_null()) { 15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Handle<Code>::null(); 157744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 15786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss, return_undefined, call_builtin; 15806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateNameCheck(name, &miss); 15827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 15836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the receiver from the stack. 15846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int argc = arguments().immediate(); 15856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 15866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the receiver isn't a smi. 15883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &miss); 15893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, 15903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 15916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the elements array of the object. 15936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); 15946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1595756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Check that the elements are in fast mode and writable. 15966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 159744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Immediate(factory()->fixed_array_map())); 1598756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ j(not_equal, &call_builtin); 15996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the array's length into ecx and calculate new length. 16016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ecx, FieldOperand(edx, JSArray::kLengthOffset)); 16023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(ecx, Immediate(Smi::FromInt(1))); 16036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(negative, &return_undefined); 16046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the last element. 16066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block STATIC_ASSERT(kSmiTagSize == 1); 16076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block STATIC_ASSERT(kSmiTag == 0); 16086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(eax, FieldOperand(ebx, 16096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ecx, times_half_pointer_size, 16106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FixedArray::kHeaderSize)); 16113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(eax, Immediate(factory()->the_hole_value())); 16126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(equal, &call_builtin); 16136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Set the array's length. 16156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(FieldOperand(edx, JSArray::kLengthOffset), ecx); 16166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Fill with the hole. 16186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(FieldOperand(ebx, 16196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ecx, times_half_pointer_size, 16206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FixedArray::kHeaderSize), 162144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Immediate(factory()->the_hole_value())); 16226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret((argc + 1) * kPointerSize); 16236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&return_undefined); 162544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(eax, Immediate(factory()->undefined_value())); 16266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret((argc + 1) * kPointerSize); 16276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&call_builtin); 162944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ TailCallExternalReference( 163044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(Builtins::c_ArrayPop, isolate()), 163144f0eee88ff00398ff7f715fab053374d808c90dSteve Block argc + 1, 163244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1); 16336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss); 16353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 16367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Return the generated code. 16387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch return GetCode(function); 16397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 16407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16423ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharCodeAtCall( 16433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 16443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 16453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 16463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 16473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 16487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------- S t a t e ------------- 16497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ecx : function name 16507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[0] : return address 16517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc - n) * 4] : arg[n] (zero-based) 16527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ... 16537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc + 1) * 4] : receiver 16547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------------------------------- 16557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1656756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // If object is not a string, bail out to regular call. 16573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsString() || !cell.is_null()) { 16583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Handle<Code>::null(); 165944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1660756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 16617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch const int argc = arguments().immediate(); 16627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label miss; 1664b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label name_miss; 16657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 1666b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label* index_out_of_range_label = &index_out_of_range; 16679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 1668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (kind_ == Code::CALL_IC && 16693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (CallICBase::StringStubState::decode(extra_state_) == 1670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DEFAULT_STRING_STUB)) { 1671b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch index_out_of_range_label = &miss; 1672b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1673b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1674b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch GenerateNameCheck(name, &name_miss); 16757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps starting from the prototype haven't changed. 16777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype(masm(), 16787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Context::STRING_FUNCTION_INDEX, 16790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen eax, 16800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &miss); 16813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!object.is_identical_to(holder)); 16823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())), 16833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch eax, holder, ebx, edx, edi, name, &miss); 16847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register receiver = ebx; 16867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = edi; 16877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = eax; 16887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); 16897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (argc > 0) { 16907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); 16917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 169244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Set(index, Immediate(factory()->undefined_value())); 16937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 16947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringCharCodeAtGenerator generator(receiver, 16963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index, 16973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result, 16983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a string. 16993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a number. 17003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index_out_of_range_label, 17013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STRING_INDEX_IS_NUMBER); 17023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateFast(masm()); 17037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ ret((argc + 1) * kPointerSize); 17047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch StubRuntimeCallHelper call_helper; 17063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateSlow(masm(), call_helper); 17077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1708b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (index_out_of_range.is_linked()) { 1709b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&index_out_of_range); 171044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Set(eax, Immediate(factory()->nan_value())); 1711b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ ret((argc + 1) * kPointerSize); 1712b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 17137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&miss); 1715b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Restore function name in ecx. 17163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Set(ecx, Immediate(name)); 1717b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&name_miss); 17183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 17197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Return the generated code. 17217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch return GetCode(function); 17227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 17237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17253ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharAtCall( 17263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 17273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 17283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 17293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 17303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 17317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------- S t a t e ------------- 17327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ecx : function name 17337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[0] : return address 17347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc - n) * 4] : arg[n] (zero-based) 17357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ... 17367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc + 1) * 4] : receiver 17377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------------------------------- 17387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1739756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // If object is not a string, bail out to regular call. 17403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsString() || !cell.is_null()) { 17413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Handle<Code>::null(); 174244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1743756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 17447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch const int argc = arguments().immediate(); 17457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label miss; 1747b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label name_miss; 17487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 1749b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label* index_out_of_range_label = &index_out_of_range; 17507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (kind_ == Code::CALL_IC && 17523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (CallICBase::StringStubState::decode(extra_state_) == 1753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DEFAULT_STRING_STUB)) { 1754b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch index_out_of_range_label = &miss; 1755b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1756b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1757b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch GenerateNameCheck(name, &name_miss); 17587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps starting from the prototype haven't changed. 17607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype(masm(), 17617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Context::STRING_FUNCTION_INDEX, 17620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen eax, 17630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &miss); 17643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!object.is_identical_to(holder)); 17653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())), 17663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch eax, holder, ebx, edx, edi, name, &miss); 17677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register receiver = eax; 17697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = edi; 17703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch = edx; 17717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = eax; 17727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); 17737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (argc > 0) { 17747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); 17757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 177644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Set(index, Immediate(factory()->undefined_value())); 17777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 17787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringCharAtGenerator generator(receiver, 17803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index, 17813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 17823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result, 17833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a string. 17843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a number. 17853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index_out_of_range_label, 17863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STRING_INDEX_IS_NUMBER); 17873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateFast(masm()); 17887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ ret((argc + 1) * kPointerSize); 17897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch StubRuntimeCallHelper call_helper; 17913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateSlow(masm(), call_helper); 17927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1793b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (index_out_of_range.is_linked()) { 1794b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&index_out_of_range); 179544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Set(eax, Immediate(factory()->empty_string())); 1796b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ ret((argc + 1) * kPointerSize); 1797b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 17987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&miss); 1800b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Restore function name in ecx. 18013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Set(ecx, Immediate(name)); 1802b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&name_miss); 18033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 18046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return the generated code. 180625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen return GetCode(function); 18076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 18086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18103ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringFromCharCodeCall( 18113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 18123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 18133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 18143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 18153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 181659151504615d929945dc59db37bf1166937748c6Steve Block // ----------- S t a t e ------------- 181759151504615d929945dc59db37bf1166937748c6Steve Block // -- ecx : function name 181859151504615d929945dc59db37bf1166937748c6Steve Block // -- esp[0] : return address 181959151504615d929945dc59db37bf1166937748c6Steve Block // -- esp[(argc - n) * 4] : arg[n] (zero-based) 182059151504615d929945dc59db37bf1166937748c6Steve Block // -- ... 182159151504615d929945dc59db37bf1166937748c6Steve Block // -- esp[(argc + 1) * 4] : receiver 182259151504615d929945dc59db37bf1166937748c6Steve Block // ----------------------------------- 182359151504615d929945dc59db37bf1166937748c6Steve Block 182459151504615d929945dc59db37bf1166937748c6Steve Block const int argc = arguments().immediate(); 182559151504615d929945dc59db37bf1166937748c6Steve Block 182659151504615d929945dc59db37bf1166937748c6Steve Block // If the object is not a JSObject or we got an unexpected number of 182759151504615d929945dc59db37bf1166937748c6Steve Block // arguments, bail out to the regular call. 182844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!object->IsJSObject() || argc != 1) { 18293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Handle<Code>::null(); 183044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 183159151504615d929945dc59db37bf1166937748c6Steve Block 183259151504615d929945dc59db37bf1166937748c6Steve Block Label miss; 183359151504615d929945dc59db37bf1166937748c6Steve Block GenerateNameCheck(name, &miss); 183459151504615d929945dc59db37bf1166937748c6Steve Block 18353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (cell.is_null()) { 183659151504615d929945dc59db37bf1166937748c6Steve Block __ mov(edx, Operand(esp, 2 * kPointerSize)); 183759151504615d929945dc59db37bf1166937748c6Steve Block STATIC_ASSERT(kSmiTag == 0); 18383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &miss); 18393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, 18403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 184159151504615d929945dc59db37bf1166937748c6Steve Block } else { 18423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(cell->value() == *function); 18433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 18443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 184559151504615d929945dc59db37bf1166937748c6Steve Block GenerateLoadFunctionFromCell(cell, function, &miss); 184659151504615d929945dc59db37bf1166937748c6Steve Block } 184759151504615d929945dc59db37bf1166937748c6Steve Block 184859151504615d929945dc59db37bf1166937748c6Steve Block // Load the char code argument. 184959151504615d929945dc59db37bf1166937748c6Steve Block Register code = ebx; 185059151504615d929945dc59db37bf1166937748c6Steve Block __ mov(code, Operand(esp, 1 * kPointerSize)); 185159151504615d929945dc59db37bf1166937748c6Steve Block 185259151504615d929945dc59db37bf1166937748c6Steve Block // Check the code is a smi. 185359151504615d929945dc59db37bf1166937748c6Steve Block Label slow; 185459151504615d929945dc59db37bf1166937748c6Steve Block STATIC_ASSERT(kSmiTag == 0); 18553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(code, &slow); 185659151504615d929945dc59db37bf1166937748c6Steve Block 185759151504615d929945dc59db37bf1166937748c6Steve Block // Convert the smi code to uint16. 185859151504615d929945dc59db37bf1166937748c6Steve Block __ and_(code, Immediate(Smi::FromInt(0xffff))); 185959151504615d929945dc59db37bf1166937748c6Steve Block 18603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringCharFromCodeGenerator generator(code, eax); 18613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateFast(masm()); 186259151504615d929945dc59db37bf1166937748c6Steve Block __ ret(2 * kPointerSize); 186359151504615d929945dc59db37bf1166937748c6Steve Block 1864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch StubRuntimeCallHelper call_helper; 18653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateSlow(masm(), call_helper); 186659151504615d929945dc59db37bf1166937748c6Steve Block 186759151504615d929945dc59db37bf1166937748c6Steve Block // Tail call the full function. We do not have to patch the receiver 186859151504615d929945dc59db37bf1166937748c6Steve Block // because the function makes no use of it. 186959151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&slow); 18703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 1871257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 1872257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 1873257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(function, arguments(), JUMP_FUNCTION, 1874257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), call_kind); 187559151504615d929945dc59db37bf1166937748c6Steve Block 187659151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&miss); 187759151504615d929945dc59db37bf1166937748c6Steve Block // ecx: function name. 18783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 187959151504615d929945dc59db37bf1166937748c6Steve Block 188059151504615d929945dc59db37bf1166937748c6Steve Block // Return the generated code. 18813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); 188259151504615d929945dc59db37bf1166937748c6Steve Block} 188359151504615d929945dc59db37bf1166937748c6Steve Block 188459151504615d929945dc59db37bf1166937748c6Steve Block 18853ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathFloorCall( 18863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 18873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 18883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 18893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 18903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 18910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // ----------- S t a t e ------------- 18920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // -- ecx : name 18930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // -- esp[0] : return address 18940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // -- esp[(argc - n) * 4] : arg[n] (zero-based) 18950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // -- ... 18960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // -- esp[(argc + 1) * 4] : receiver 18970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // ----------------------------------- 18980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 18998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (!CpuFeatures::IsSupported(SSE2)) { 19003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Handle<Code>::null(); 190144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 190244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 19030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CpuFeatures::Scope use_sse2(SSE2); 19040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen const int argc = arguments().immediate(); 19060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // If the object is not a JSObject or we got an unexpected number of 19080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // arguments, bail out to the regular call. 190944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!object->IsJSObject() || argc != 1) { 19103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Handle<Code>::null(); 191144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 19120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label miss; 19140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen GenerateNameCheck(name, &miss); 19150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (cell.is_null()) { 19170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(edx, Operand(esp, 2 * kPointerSize)); 19180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen STATIC_ASSERT(kSmiTag == 0); 19203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &miss); 19210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, 19233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 19240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 19253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(cell->value() == *function); 19263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 19273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 19280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen GenerateLoadFunctionFromCell(cell, function, &miss); 19290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 19300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Load the (only) argument into eax. 19320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(eax, Operand(esp, 1 * kPointerSize)); 19330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Check if the argument is a smi. 19350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label smi; 19360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen STATIC_ASSERT(kSmiTag == 0); 19373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(eax, &smi); 19380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Check if the argument is a heap number and load its value into xmm0. 19400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label slow; 1941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CheckMap(eax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK); 19420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ movdbl(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); 19430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Check if the argument is strictly positive. Note this also 19450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // discards NaN. 19460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ xorpd(xmm1, xmm1); 19470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ ucomisd(xmm0, xmm1); 19480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ j(below_equal, &slow); 19490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Do a truncating conversion. 19510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ cvttsd2si(eax, Operand(xmm0)); 19520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Check if the result fits into a smi. Note this also checks for 19540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // 0x80000000 which signals a failed conversion. 19550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label wont_fit_into_smi; 19560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ test(eax, Immediate(0xc0000000)); 19570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ j(not_zero, &wont_fit_into_smi); 19580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Smi tag and return. 19600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ SmiTag(eax); 19610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&smi); 19620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ ret(2 * kPointerSize); 19630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Check if the argument is < 2^kMantissaBits. 19650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label already_round; 19660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&wont_fit_into_smi); 19670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadPowerOf2(xmm1, ebx, HeapNumber::kMantissaBits); 19680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ ucomisd(xmm0, xmm1); 19690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ j(above_equal, &already_round); 19700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Save a copy of the argument. 19720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ movaps(xmm2, xmm0); 19730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Compute (argument + 2^kMantissaBits) - 2^kMantissaBits. 19750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ addsd(xmm0, xmm1); 19760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ subsd(xmm0, xmm1); 19770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Compare the argument and the tentative result to get the right mask: 19790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // if xmm2 < xmm0: 19800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // xmm2 = 1...1 19810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // else: 19820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // xmm2 = 0...0 19830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ cmpltsd(xmm2, xmm0); 19840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Subtract 1 if the argument was less than the tentative result. 19860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadPowerOf2(xmm1, ebx, 0); 19870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ andpd(xmm1, xmm2); 19880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ subsd(xmm0, xmm1); 19890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Return a new heap number. 19910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ AllocateHeapNumber(eax, ebx, edx, &slow); 19920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); 19930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ ret(2 * kPointerSize); 19940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Return the argument (when it's an already round heap number). 19960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&already_round); 19970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(eax, Operand(esp, 1 * kPointerSize)); 19980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ ret(2 * kPointerSize); 19990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 20000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Tail call the full function. We do not have to patch the receiver 20010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // because the function makes no use of it. 20020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&slow); 2003257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(function, arguments(), JUMP_FUNCTION, 2004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), CALL_AS_METHOD); 20050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 20060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&miss); 20070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // ecx: function name. 20083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 20090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 20100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Return the generated code. 20113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); 20120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 20130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 20140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 20153ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathAbsCall( 20163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 20173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 20183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 20193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 20203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2021f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // ----------- S t a t e ------------- 2022f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- ecx : name 2023f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- esp[0] : return address 2024f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- esp[(argc - n) * 4] : arg[n] (zero-based) 2025f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- ... 2026f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- esp[(argc + 1) * 4] : receiver 2027f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // ----------------------------------- 2028f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2029f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch const int argc = arguments().immediate(); 2030f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2031f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // If the object is not a JSObject or we got an unexpected number of 2032f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // arguments, bail out to the regular call. 203344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!object->IsJSObject() || argc != 1) { 20343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Handle<Code>::null(); 203544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 2036f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2037f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Label miss; 2038f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch GenerateNameCheck(name, &miss); 2039f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 20403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (cell.is_null()) { 2041f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ mov(edx, Operand(esp, 2 * kPointerSize)); 2042f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2043f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch STATIC_ASSERT(kSmiTag == 0); 20443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &miss); 2045f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 20463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, 20473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 2048f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch } else { 20493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(cell->value() == *function); 20503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 20513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 2052f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch GenerateLoadFunctionFromCell(cell, function, &miss); 2053f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch } 2054f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2055f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Load the (only) argument into eax. 2056f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ mov(eax, Operand(esp, 1 * kPointerSize)); 2057f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2058f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Check if the argument is a smi. 2059f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Label not_smi; 2060f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch STATIC_ASSERT(kSmiTag == 0); 20613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(eax, ¬_smi); 2062f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2063f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0 2064f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // otherwise. 2065f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ mov(ebx, eax); 2066f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ sar(ebx, kBitsPerInt - 1); 2067f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2068f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Do bitwise not or do nothing depending on ebx. 20693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ xor_(eax, ebx); 2070f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2071f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Add 1 or do nothing depending on ebx. 20723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(eax, ebx); 2073f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2074f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // If the result is still negative, go to the slow case. 2075f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // This only happens for the most negative smi. 2076f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Label slow; 2077f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ j(negative, &slow); 2078f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2079f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Smi case done. 2080f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ ret(2 * kPointerSize); 2081f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2082f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Check if the argument is a heap number and load its exponent and 2083f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // sign into ebx. 2084f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(¬_smi); 2085257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CheckMap(eax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK); 2086f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ mov(ebx, FieldOperand(eax, HeapNumber::kExponentOffset)); 2087f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2088f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Check the sign of the argument. If the argument is positive, 2089f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // just return it. 2090f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Label negative_sign; 2091f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ test(ebx, Immediate(HeapNumber::kSignMask)); 2092f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ j(not_zero, &negative_sign); 2093f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ ret(2 * kPointerSize); 2094f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2095f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // If the argument is negative, clear the sign, and return a new 2096f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // number. 2097f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(&negative_sign); 2098f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ and_(ebx, ~HeapNumber::kSignMask); 2099f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ mov(ecx, FieldOperand(eax, HeapNumber::kMantissaOffset)); 2100f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ AllocateHeapNumber(eax, edi, edx, &slow); 2101f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ebx); 2102f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); 2103f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ ret(2 * kPointerSize); 2104f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2105f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Tail call the full function. We do not have to patch the receiver 2106f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // because the function makes no use of it. 2107f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(&slow); 2108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(function, arguments(), JUMP_FUNCTION, 2109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), CALL_AS_METHOD); 2110f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2111f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(&miss); 2112f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // ecx: function name. 21133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2114f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2115f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Return the generated code. 21163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); 2117f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch} 2118f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2119f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 21203ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileFastApiCall( 212144f0eee88ff00398ff7f715fab053374d808c90dSteve Block const CallOptimization& optimization, 21223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 21233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 21243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 21253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 21263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 212744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(optimization.is_simple_api_call()); 212844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Bail out if object is a global object as we don't want to 212944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // repatch it to global receiver. 21303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (object->IsGlobalObject()) return Handle<Code>::null(); 21313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!cell.is_null()) return Handle<Code>::null(); 21323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSObject()) return Handle<Code>::null(); 213344f0eee88ff00398ff7f715fab053374d808c90dSteve Block int depth = optimization.GetPrototypeDepthOfExpectedType( 21343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>::cast(object), holder); 21353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (depth == kInvalidProtoDepth) return Handle<Code>::null(); 213644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 213744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label miss, miss_before_stack_reserved; 213844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 213944f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenerateNameCheck(name, &miss_before_stack_reserved); 214044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 214144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Get the receiver from the stack. 214244f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int argc = arguments().immediate(); 214344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 214444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 214544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the receiver isn't a smi. 21463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &miss_before_stack_reserved); 214744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 214844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 214944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_const(), 1); 215044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_const_fast_api(), 1); 215144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 215244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Allocate space for v8::Arguments implicit values. Must be initialized 215344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // before calling any runtime function. 21543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(esp, Immediate(kFastApiCallArguments * kPointerSize)); 215544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 215644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the maps haven't changed and find a Holder as a side effect. 21573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, 21583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, depth, &miss); 215944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 216044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Move the return address on top of the stack. 216144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(eax, Operand(esp, 3 * kPointerSize)); 216244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(Operand(esp, 0 * kPointerSize), eax); 216344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 216444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains 216544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // duplicate of return address and will be overwritten. 21663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateFastApiCall(masm(), optimization, argc); 216744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 216844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&miss); 21693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); 217044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 217144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&miss_before_stack_reserved); 21723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 217344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 217444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Return the generated code. 217544f0eee88ff00398ff7f715fab053374d808c90dSteve Block return GetCode(function); 217644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 217744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 217844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 21793ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object, 21803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 21813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 21823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 21833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckType check) { 2184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2185e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 2186e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 2187e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 2188e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 2189e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 2190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 21916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 219244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (HasCustomCallGenerator(function)) { 21933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = CompileCustomCall(object, holder, 21943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell>::null(), 21953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function, name); 21963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // A null handle means bail out to the regular compiler code below. 21973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!code.is_null()) return code; 21986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 21996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 220044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label miss; 220144f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenerateNameCheck(name, &miss); 22027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver from the stack. 2204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 2205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 2206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 2208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check != NUMBER_CHECK) { 22093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &miss); 2210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure that it's okay not to patch the on stack receiver 2213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // unless we're doing a receiver map check. 2214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); 2215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (check) { 2216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case RECEIVER_MAP_CHECK: 221744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(isolate()->counters()->call_const(), 1); 2218402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 2219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 22203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, 22213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch edi, name, &miss); 2222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack with the global proxy if 2224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // necessary. 2225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsGlobalObject()) { 2226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 2227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 2228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 2230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case STRING_CHECK: 22323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (function->IsBuiltin() || !function->shared()->is_classic_mode()) { 2233e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the object is a string or a symbol. 22347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax); 2235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above_equal, &miss); 2236e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the maps starting from the prototype haven't changed. 22377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype( 22380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen masm(), Context::STRING_FUNCTION_INDEX, eax, &miss); 22393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes( 22403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(JSObject::cast(object->GetPrototype())), 22413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch eax, holder, ebx, edx, edi, name, &miss); 22423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 224385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // Calling non-strict non-builtins with a value as the receiver 224485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // requires boxing. 224585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch __ jmp(&miss); 22463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 22473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 22483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 22493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case NUMBER_CHECK: 22503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (function->IsBuiltin() || !function->shared()->is_classic_mode()) { 2251e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label fast; 2252e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the object is a smi or a heap number. 22533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &fast); 2254e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); 2255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2256e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&fast); 2257e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the maps starting from the prototype haven't changed. 22587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype( 22590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss); 22603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes( 22613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(JSObject::cast(object->GetPrototype())), 22623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch eax, holder, ebx, edx, edi, name, &miss); 22633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 226485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // Calling non-strict non-builtins with a value as the receiver 226585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // requires boxing. 226685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch __ jmp(&miss); 22673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 22683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 22693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 22703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case BOOLEAN_CHECK: 22713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (function->IsBuiltin() || !function->shared()->is_classic_mode()) { 2272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label fast; 2273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the object is a boolean. 227444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(edx, factory()->true_value()); 2275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &fast); 227644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(edx, factory()->false_value()); 2277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2278e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&fast); 2279e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the maps starting from the prototype haven't changed. 22807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype( 22810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss); 22823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes( 22833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(JSObject::cast(object->GetPrototype())), 22843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch eax, holder, ebx, edx, edi, name, &miss); 22853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 22863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Calling non-strict non-builtins with a value as the receiver 22873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // requires boxing. 22883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&miss); 2289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 2291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 22933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 2295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 2296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(function, arguments(), JUMP_FUNCTION, 2297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), call_kind); 2298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 2300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 23013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 230425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen return GetCode(function); 2305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23083ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, 23093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 23103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 2313e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 2314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 2315e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 2316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 2317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateNameCheck(name, &miss); 23217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the number of arguments. 2323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 2324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 2326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupPostInterceptor(holder, name, &lookup); 2327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver from the stack. 2329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 2330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallInterceptorCompiler compiler(this, arguments(), ecx, extra_state_); 23323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch compiler.Compile(masm(), object, holder, name, &lookup, edx, ebx, edi, eax, 23333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 2334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore receiver. 2336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 2337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the function really is a function. 23393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(eax, &miss); 2340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); 2341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack with the global proxy if 2344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // necessary. 2345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsGlobalObject()) { 2346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 2347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 2348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the function. 2351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edi, eax); 23523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2353257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 2354257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 2355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, 2356257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), call_kind); 2357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle load cache miss. 2359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 23603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23673ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallGlobal( 23683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 23693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject> holder, 23703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 23713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 23723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 2375e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 2376e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 2377e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 2378e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 2379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 238059151504615d929945dc59db37bf1166937748c6Steve Block 238144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (HasCustomCallGenerator(function)) { 23823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = CompileCustomCall(object, holder, cell, function, name); 23833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // A null handle means bail out to the regular compiler code below. 23843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!code.is_null()) return code; 238559151504615d929945dc59db37bf1166937748c6Steve Block } 238659151504615d929945dc59db37bf1166937748c6Steve Block 2387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 23887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateNameCheck(name, &miss); 23897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the number of arguments. 2391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 239259151504615d929945dc59db37bf1166937748c6Steve Block GenerateGlobalReceiverCheck(object, holder, name, &miss); 239359151504615d929945dc59db37bf1166937748c6Steve Block GenerateLoadFunctionFromCell(cell, function, &miss); 2394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack with the global proxy. 2396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsGlobalObject()) { 2397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 2398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 2399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the context (function already in edi). 2402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 2403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the cached code (tail call). 240544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 240644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_global_inline(), 1); 2407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount expected(function->shared()->formal_parameter_count()); 24083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 2410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 24113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We call indirectly through the code field in the function to 24123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // allow recompilation to take effect without changing any of the 24133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // call sites. 24143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), 24153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expected, arguments(), JUMP_FUNCTION, 24163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch NullCallWrapper(), call_kind); 2417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 2419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 242044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_global_inline_miss(), 1); 24213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(NORMAL, name); 2425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24283ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, 24295913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index, 24303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> transition, 24313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 2434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 24354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- edx : receiver 2436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Generate store field code. Trashes the name register. 24413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateStoreField(masm(), object, index, transition, edx, ecx, ebx, &miss); 2442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 24453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ecx, Immediate(name)); // restore name 244644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); 2447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(ic, RelocInfo::CODE_TARGET); 2448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 24503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); 2451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24543ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreCallback( 24553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 24563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback, 24573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 2460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 24614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- edx : receiver 2462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the object hasn't changed. 24673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(edx, Handle<Map>(object->map()), 24683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); 2469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform global security token check if needed. 2471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsJSGlobalProxy()) { 24724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CheckAccessGlobalProxy(edx, ebx, &miss); 2473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stub never generated for non-global objects that require access 2476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks. 2477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 2478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); // remove the return address 24804515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(edx); // receiver 24813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(Immediate(callback)); // callback info 2482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); // name 2483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(eax); // value 2484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); // restore return address 2485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to the runtime system. 2487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference store_callback_property = 248844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); 24896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(store_callback_property, 4, 1); 2490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 249344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); 2494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(ic, RelocInfo::CODE_TARGET); 2495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25013ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreInterceptor( 25023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 25033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 2506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 25074515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- edx : receiver 2508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the object hasn't changed. 25133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(edx, Handle<Map>(receiver->map()), 25143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); 2515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform global security token check if needed. 2517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (receiver->IsJSGlobalProxy()) { 25184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CheckAccessGlobalProxy(edx, ebx, &miss); 2519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stub never generated for non-global objects that require access 2522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks. 2523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); 2524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); // remove the return address 25264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(edx); // receiver 2527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); // name 2528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(eax); // value 2529e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(Immediate(Smi::FromInt(strict_mode_))); 2530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); // restore return address 2531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to the runtime system. 2533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference store_ic_property = 253444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); 2535e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ TailCallExternalReference(store_ic_property, 4, 1); 2536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 253944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); 2540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(ic, RelocInfo::CODE_TARGET); 2541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25473ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreGlobal( 25483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject> object, 25493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 25503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 2553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 25544515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- edx : receiver 2555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the global has not changed. 25604515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ cmp(FieldOperand(edx, HeapObject::kMapOffset), 2561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(Handle<Map>(object->map()))); 2562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Compute the cell operand to use. 25653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ebx, Immediate(cell)); 25663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset); 2567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the value in the cell is not the hole. If it is, this 25691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // cell could have been deleted and reintroducing the global needs 25701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // to update the property details in the property dictionary of the 25711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // global object. We bail out to the runtime system to do that. 257244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(cell_operand, factory()->the_hole_value()); 25731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(equal, &miss); 25741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 25751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Store the value in the cell. 25761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(cell_operand, eax); 25773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // No write barrier here, because cells are always rescanned. 25781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the value (register eax). 258044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 258144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_store_global_inline(), 1); 2582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 2583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 258644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_store_global_inline_miss(), 1); 258744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); 2588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(ic, RelocInfo::CODE_TARGET); 2589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(NORMAL, name); 2592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25953ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object, 25965913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index, 25973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> transition, 25983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 26016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : key 26026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- edx : receiver 2603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 260744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 260844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_store_field(), 1); 2609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 26113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(ecx, Immediate(name)); 2612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Generate store field code. Trashes the name register. 26153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateStoreField(masm(), object, index, transition, edx, ecx, ebx, &miss); 2616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 261944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_store_field(), 1); 262044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(ic, RelocInfo::CODE_TARGET); 2622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 26243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); 2625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 26283ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreElement( 26293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> receiver_map) { 2630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------- S t a t e ------------- 2631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- eax : value 2632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- ecx : key 2633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- edx : receiver 2634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- esp[0] : return address 2635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------------------------------- 2636589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind = receiver_map->elements_kind(); 26373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE; 26383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> stub = 26393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch KeyedStoreElementStub(is_jsarray, elements_kind, grow_mode_).GetCode(); 26403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); 2642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(ic, RelocInfo::CODE_TARGET); 2645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 26473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string()); 2648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 26513ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( 26523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MapHandleList* receiver_maps, 26533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CodeHandleList* handler_stubs, 26543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MapHandleList* transitioned_maps) { 2655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- eax : value 2657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ecx : key 2658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- edx : receiver 2659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- esp[0] : return address 2660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 26623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(edx, &miss, Label::kNear); 26633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); 26643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ebx: receiver->map(). 26653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < receiver_maps->length(); ++i) { 26663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(edi, receiver_maps->at(i)); 26673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (transitioned_maps->at(i).is_null()) { 26683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, handler_stubs->at(i)); 26693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 26703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label next_map; 26713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &next_map, Label::kNear); 26723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ebx, Immediate(transitioned_maps->at(i))); 26733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET); 26743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&next_map); 26753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&miss); 2678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(miss_ic, RelocInfo::CODE_TARGET); 2680e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2681e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Return the generated code. 26823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); 2683e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2684e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2685e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 26863ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name, 26873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 26883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> last) { 26896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 26906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- eax : receiver 26916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : name 26926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[0] : return address 26936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 26946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss; 26956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 26966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the receiver isn't a smi. 26973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(eax, &miss); 26986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 26998defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(last->IsGlobalObject() || last->HasFastProperties()); 27008defd9ff6930b4e24729971a61cf7469daf119beSteve Block 27016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check the maps of the full prototype chain. Also check that 27026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // global property cells up to (but not including) the last object 27036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // in the prototype chain are empty. 27043bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss); 27056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 27066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // If the last object in the prototype chain is a global object, 27076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // check that the global property cell is empty. 27086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (last->IsGlobalObject()) { 27093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateCheckPropertyCell( 27103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm(), Handle<GlobalObject>::cast(last), name, edx, &miss); 27116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 27126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 27136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return undefined if maps of the full prototype chain are still the 27146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // same and no global property with this name contains a value. 271544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(eax, isolate()->factory()->undefined_value()); 27166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret(0); 27176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 27186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss); 27196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 27206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 27216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return the generated code. 27223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NONEXISTENT, factory()->empty_string()); 27236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 27246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27263ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object, 27273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 27285913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index, 27293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2731402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 2732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 2733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch GenerateLoadField(object, holder, eax, ebx, edx, edi, index, name, &miss); 2738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(FIELD, name); 2743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27463ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadCallback( 27473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 27483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 27493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 27503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback) { 2751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2752402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 2753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 2754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadCallback(object, holder, eax, ecx, ebx, edx, edi, callback, 27593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 2760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27683ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object, 27693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 27703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> value, 27713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2773402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 2774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 2775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch GenerateLoadConstant(object, holder, eax, ebx, edx, edi, value, name, &miss); 2780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CONSTANT_FUNCTION, name); 2785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27883ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> receiver, 27893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 27903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2792402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 2793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 2794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 2799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupPostInterceptor(holder, name, &lookup); 2800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // TODO(368): Compile in the whole chain: all the interceptors in 2802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // prototypes and ultimate answer. 28033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadInterceptor(receiver, holder, &lookup, eax, ecx, edx, ebx, edi, 28043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 2805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28143ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadGlobal( 28153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 28163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject> holder, 28173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 28183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 28193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_dont_delete) { 2820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2821402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 2822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 2823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 28283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(eax, &miss); 28293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CheckPrototypes(object, eax, holder, ebx, edx, edi, name, &miss); 2830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the value from the cell. 2832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (Serializer::enabled()) { 28333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ebx, Immediate(cell)); 2834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); 2835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 28363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ebx, Operand::Cell(cell)); 2837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for deleted property if property can actually be deleted. 2840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!is_dont_delete) { 284144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(ebx, factory()->the_hole_value()); 2842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &miss); 2843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (FLAG_debug_code) { 284444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(ebx, factory()->the_hole_value()); 2845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Check(not_equal, "DontDelete cells can't contain the hole"); 2846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 284844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 284944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_load_global_stub(), 1); 2850402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, ebx); 2851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 2852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 285444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_load_global_stub_miss(), 1); 2855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(NORMAL, name); 2859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28623ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name, 28633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 28643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 28655913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index) { 2866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2867402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 2868402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 2869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 287344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 287444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_field(), 1); 2875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 28773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(eax, Immediate(name)); 2878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28803bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); 2881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 288344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_field(), 1); 2884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(FIELD, name); 2888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28913ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadCallback( 28923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 28933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 28943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 28953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback) { 2896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2897402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 2898402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 2899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 290344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 290444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_callback(), 1); 2905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 29073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(eax, Immediate(name)); 2908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadCallback(receiver, holder, edx, eax, ebx, ecx, edi, callback, 29113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 2912e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 291444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_callback(), 1); 2915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29223ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadConstant( 29233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 29243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 29253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 29263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> value) { 2927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2928402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 2929402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 2930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 293444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 293544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_constant_function(), 1); 2936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 29383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(eax, Immediate(name)); 2939257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadConstant( 29423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver, holder, edx, ebx, ecx, edi, value, name, &miss); 2943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 294444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_constant_function(), 1); 2945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CONSTANT_FUNCTION, name); 2949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29523ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor( 29533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 29543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 29553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2957402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 2958402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 2959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 296344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 296444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_interceptor(), 1); 2965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 29673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(eax, Immediate(name)); 2968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 2971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupPostInterceptor(holder, name, &lookup); 29723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadInterceptor(receiver, holder, &lookup, edx, eax, ecx, ebx, edi, 29733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 2974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 297544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_interceptor(), 1); 2976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29833ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength( 29843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2986402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 2987402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 2988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 299244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 299344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_array_length(), 1); 2994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 29963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(eax, Immediate(name)); 2997257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2999402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateLoadArrayLength(masm(), edx, ecx, &miss); 3000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 300144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_array_length(), 1); 3002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 3005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 3006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30093ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadStringLength( 30103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 3011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 3012402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 3013402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 3014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 3015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 3016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 3017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 301844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 301944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_string_length(), 1); 3020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 30223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(eax, Immediate(name)); 3023257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 3024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true); 3026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 302744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_string_length(), 1); 3028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 3031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 3032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30353ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype( 30363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 3037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 3038402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 3039402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 3040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 3041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 3042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 3043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 304444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 304544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_function_prototype(), 1); 3046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 30483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(eax, Immediate(name)); 3049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 3050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3051402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); 3052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 305344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_function_prototype(), 1); 3054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 3057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 3058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30613ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadElement( 30623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> receiver_map) { 3063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------- S t a t e ------------- 3064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- eax : key 3065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- edx : receiver 3066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- esp[0] : return address 3067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------------------------------- 30683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3069589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind = receiver_map->elements_kind(); 30703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode(); 30713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); 3073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 30773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string()); 3078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 30813ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( 30823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MapHandleList* receiver_maps, 30833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CodeHandleList* handler_ics) { 3084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3085257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- eax : key 3086257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- edx : receiver 3087257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- esp[0] : return address 3088257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3089257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 3090257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(edx, &miss); 3091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register map_reg = ebx; 3093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(map_reg, FieldOperand(edx, HeapObject::kMapOffset)); 3094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int receiver_count = receiver_maps->length(); 3095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int current = 0; current < receiver_count; ++current) { 30963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(map_reg, receiver_maps->at(current)); 30973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, handler_ics->at(current)); 3098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&miss); 3101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Return the generated code. 31043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); 3105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Specialized stub for constructing objects from functions which only have only 3109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// simple assignments of the form this.x = ...; in their body. 31103ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> ConstructStubCompiler::CompileConstructStub( 31113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function) { 3112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 3113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : argc 3114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- edi : constructor 3115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 3116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[4] : last argument 3117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 3118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label generic_stub_call; 3119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 3120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check to see whether there are any break points in the function code. If 3121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // there are jump to the generic constructor stub which calls the actual 3122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // code for the function thereby hitting the break points. 3123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 3124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kDebugInfoOffset)); 312544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(ebx, factory()->undefined_value()); 3126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &generic_stub_call); 3127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 3128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the initial map and verify that it is in fact a map. 3130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); 3131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Will both indicate a NULL and a Smi. 31323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(ebx, &generic_stub_call); 3133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpObjectType(ebx, MAP_TYPE, ecx); 3134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &generic_stub_call); 3135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 3137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cannot construct functions this way. 3138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edi: constructor 3139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ebx: initial map 3140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpInstanceType(ebx, JS_FUNCTION_TYPE); 3141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Assert(not_equal, "Function constructed by construct stub."); 3142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 3143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Now allocate the JSObject on the heap by moving the new space allocation 3145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // top forward. 3146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edi: constructor 3147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ebx: initial map 3148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset)); 3149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ shl(ecx, kPointerSizeLog2); 31503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(ecx, edx, ecx, no_reg, 31513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &generic_stub_call, NO_ALLOCATION_FLAGS); 3152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocated the JSObject, now initialize the fields and add the heap tag. 3154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ebx: initial map 3155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edx: JSObject (untagged) 3156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(edx, JSObject::kMapOffset), ebx); 315744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(ebx, factory()->empty_fixed_array()); 3158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(edx, JSObject::kPropertiesOffset), ebx); 3159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(edx, JSObject::kElementsOffset), ebx); 3160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push the allocated object to the stack. This is the object that will be 3162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // returned (after it is tagged). 3163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(edx); 3164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: argc 3166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edx: JSObject (untagged) 3167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the address of the first in-object property into edx. 3168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(edx, Operand(edx, JSObject::kHeaderSize)); 3169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the location of the first argument. The stack contains the 3170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // allocated object and the return address on top of the argc arguments. 3171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(ecx, Operand(esp, eax, times_4, 1 * kPointerSize)); 3172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use edi for holding undefined which is used in several places below. 317444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(edi, factory()->undefined_value()); 3175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: argc 3177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ecx: first argument 3178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edx: first in-object property of the JSObject 3179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edi: undefined 3180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the initialized properties with a constant value or a passed argument 3181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // depending on the this.x = ...; assignment in the function. 31823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<SharedFunctionInfo> shared(function->shared()); 3183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < shared->this_property_assignments_count(); i++) { 3184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (shared->IsThisPropertyAssignmentArgument(i)) { 3185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the argument assigned to the property is actually passed. 3186e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // If argument is not passed the property is set to undefined, 3187e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // otherwise find it on the stack. 3188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int arg_number = shared->GetThisPropertyAssignmentArgument(i); 3189e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(ebx, edi); 3190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, arg_number); 31918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CpuFeatures::IsSupported(CMOV)) { 3192e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke CpuFeatures::Scope use_cmov(CMOV); 3193e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmov(above, ebx, Operand(ecx, arg_number * -kPointerSize)); 3194e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 3195e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label not_passed; 3196e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(below_equal, ¬_passed); 3197e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(ebx, Operand(ecx, arg_number * -kPointerSize)); 3198e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(¬_passed); 3199e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3200e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store value in the property. 3201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(edx, i * kPointerSize), ebx); 3202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 3203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the property to the constant value. 3204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i)); 3205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(edx, i * kPointerSize), Immediate(constant)); 3206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the unused in-object property fields with undefined. 32108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ASSERT(function->has_initial_map()); 3211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = shared->this_property_assignments_count(); 32128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang i < function->initial_map()->inobject_properties(); 3213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i++) { 3214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(edx, i * kPointerSize), edi); 3215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move argc to ebx and retrieve and tag the JSObject to return. 3218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, eax); 3219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(eax); 32203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ or_(eax, Immediate(kHeapObjectTag)); 3221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Remove caller arguments and receiver from the stack and return. 3223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ecx); 3224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(esp, Operand(esp, ebx, times_pointer_size, 1 * kPointerSize)); 3225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); 322644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 322744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->constructed_objects(), 1); 322844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->constructed_objects_stub(), 1); 3229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 3230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the generic stub in case the specialized code cannot handle the 3232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // construction. 3233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&generic_stub_call); 32343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = isolate()->builtins()->JSConstructStubGeneric(); 32353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(code, RelocInfo::CODE_TARGET); 3236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 3238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(); 3239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 32423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#undef __ 32433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#define __ ACCESS_MASM(masm) 32443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 32453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 32463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadDictionaryElement( 32473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MacroAssembler* masm) { 32481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------- S t a t e ------------- 32491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- eax : key 32501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- edx : receiver 32511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- esp[0] : return address 32521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 32533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label slow, miss_force_generic; 3254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 32553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 32563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // have been verified by the caller to not be a smi. 32573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(eax, &miss_force_generic); 32583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(ebx, eax); 32593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ SmiUntag(ebx); 32603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); 32611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 32623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Push receiver on the stack to free up a register for the dictionary 32633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // probing. 32643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ push(edx); 32653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ LoadFromNumberDictionary(&slow, 32663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ecx, 32673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch eax, 32683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ebx, 32693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch edx, 32703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch edi, 32713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch eax); 32723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Pop receiver before returning. 32733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ pop(edx); 32743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ret(0); 3275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 32763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&slow); 32773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ pop(edx); 3278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- eax : value 3281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ecx : key 3282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- edx : receiver 3283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- esp[0] : return address 3284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 32863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> slow_ic = 32873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_Slow(); 32883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(slow_ic, RelocInfo::CODE_TARGET); 3289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 32903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&miss_force_generic); 32913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------- S t a t e ------------- 32923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- eax : value 32933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- ecx : key 32943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- edx : receiver 32953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- esp[0] : return address 32963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------------------------------- 3297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 32983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> miss_force_generic_ic = 32993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 33003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(miss_force_generic_ic, RelocInfo::CODE_TARGET); 33013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 3302257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadExternalArray( 3305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MacroAssembler* masm, 3306589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind) { 3307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3308257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- eax : key 3309257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- edx : receiver 3310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- esp[0] : return address 3311257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss_force_generic, failed_allocation, slow; 3313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 3315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 33161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the key is a smi. 33183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(eax, &miss_force_generic); 33191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the index is in range. 3321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); 332269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmp(eax, FieldOperand(ebx, ExternalArray::kLengthOffset)); 33231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Unsigned comparison catches both negative and too-large values. 3324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above_equal, &miss_force_generic); 33251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset)); 33261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ebx: base pointer of external storage 33273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3328589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 332969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ SmiUntag(eax); // Untag the index. 333069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movsx_b(eax, Operand(ebx, eax, times_1, 0)); 33311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3332589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 3333589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 333469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ SmiUntag(eax); // Untag the index. 333569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movzx_b(eax, Operand(ebx, eax, times_1, 0)); 33361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3337589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 333869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movsx_w(eax, Operand(ebx, eax, times_1, 0)); 33391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3340589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 334169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movzx_w(eax, Operand(ebx, eax, times_1, 0)); 33421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3343589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 3344589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 334569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov(ecx, Operand(ebx, eax, times_2, 0)); 33461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3347589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 334869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ fld_s(Operand(ebx, eax, times_2, 0)); 33491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3350589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 335169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ fld_d(Operand(ebx, eax, times_4, 0)); 3352257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 33531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block default: 33541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 33551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 33561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 33571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For integer array types: 33591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ecx: value 33601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For floating-point array type: 33611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // FP(0): value 33621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3363589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_INT_ELEMENTS || 3364589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { 33651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For the Int and UnsignedInt array types, we need to see whether 33661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the value can be represented in a Smi. If not, we need to convert 33671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // it to a HeapNumber. 33681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label box_int; 3369589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_INT_ELEMENTS) { 33701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmp(ecx, 0xC0000000); 33711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(sign, &box_int); 33721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 3373589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind); 33741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // The test is different for unsigned int values. Since we need 33751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the value to be in the range of a positive smi, we can't 33761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // handle either of the top two bits being set in the value. 33771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ test(ecx, Immediate(0xC0000000)); 33781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(not_zero, &box_int); 33791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 33801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(eax, ecx); 33821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ SmiTag(eax); 33831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 33841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&box_int); 33861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Allocate a HeapNumber for the int and perform int-to-double 33881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // conversion. 3389589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_INT_ELEMENTS) { 33901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(ecx); 33911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ fild_s(Operand(esp, 0)); 33921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ pop(ecx); 33931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 3394589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind); 33951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Need to zero-extend the value. 33961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // There's no fild variant for unsigned values, so zero-extend 33971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // to a 64-bit int manually. 33981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(Immediate(0)); 33991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(ecx); 34001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ fild_d(Operand(esp, 0)); 34011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ pop(ecx); 34021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ pop(ecx); 34031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 34041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // FP(0): value 34051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); 34061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Set the value. 34071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(eax, ecx); 34081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 34091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 3410589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || 3411589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 34121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For the floating-point array type, we need to always allocate a 34131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // HeapNumber. 34141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); 34151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Set the value. 34161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(eax, ecx); 34171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 34181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 34191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 34201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ SmiTag(eax); 34211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 34221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 34231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // If we fail allocation of the HeapNumber, we still have a value on 34251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // top of the FPU stack. Remove it. 34261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&failed_allocation); 34273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fstp(0); 34281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Fall through to slow case. 34291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Slow case: Jump to runtime. 34311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&slow); 3432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Counters* counters = masm->isolate()->counters(); 343344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_external_array_slow(), 1); 3434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 34351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------- S t a t e ------------- 34361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- eax : key 34371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- edx : receiver 34381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- esp[0] : return address 34391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 34401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Slow(); 3442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(ic, RelocInfo::CODE_TARGET); 34431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- eax : key 3446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- edx : receiver 3447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- esp[0] : return address 3448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 34491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Miss case: Jump to runtime. 3451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 3452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> miss_ic = 3453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 3454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(miss_ic, RelocInfo::CODE_TARGET); 34551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 34561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreExternalArray( 3459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MacroAssembler* masm, 3460589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind) { 34611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------- S t a t e ------------- 3462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- eax : key 34631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- edx : receiver 34641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- esp[0] : return address 34651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 3466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss_force_generic, slow, check_heap_number; 346744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 3469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 347044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 34711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the key is a smi. 34723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(ecx, &miss_force_generic); 34731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the index is in range. 347544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 347669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmp(ecx, FieldOperand(edi, ExternalArray::kLengthOffset)); 34771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Unsigned comparison catches both negative and too-large values. 34781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(above_equal, &slow); 34791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Handle both smis and HeapNumbers in the fast path. Go to the 34811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // runtime for all other kinds of values. 34821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // eax: value 34831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // edx: receiver 34841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ecx: key 34851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // edi: elements array 3486589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) { 34873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(eax, &slow); 34883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 34893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(eax, &check_heap_number); 34903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 349144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 34921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // smi case 349369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov(ebx, eax); // Preserve the value in eax as the return value. 349469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ SmiUntag(ebx); 34951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); 349669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // edi: base pointer of external storage 34973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3498589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 349969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ ClampUint8(ebx); 350069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ SmiUntag(ecx); 350169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov_b(Operand(edi, ecx, times_1, 0), ebx); 350244f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3503589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 3504589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 350569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ SmiUntag(ecx); 350669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov_b(Operand(edi, ecx, times_1, 0), ebx); 35071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3508589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 3509589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 351069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov_w(Operand(edi, ecx, times_1, 0), ebx); 35111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3512589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 3513589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 351469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov(Operand(edi, ecx, times_2, 0), ebx); 35151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3516589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 3517589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 35181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Need to perform int-to-float conversion. 351969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ push(ebx); 35201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ fild_s(Operand(esp, 0)); 352169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ pop(ebx); 3522589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 352369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ fstp_s(Operand(edi, ecx, times_2, 0)); 3524589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { // elements_kind == EXTERNAL_DOUBLE_ELEMENTS. 352569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ fstp_d(Operand(edi, ecx, times_4, 0)); 3526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 35271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 35281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block default: 35291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 35301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 35311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 35321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); // Return the original value. 35331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 353444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // TODO(danno): handle heap number -> pixel array conversion 3535589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) { 353644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&check_heap_number); 353744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // eax: value 353844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // edx: receiver 353944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // ecx: key 354044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // edi: elements array 354144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 3542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Immediate(masm->isolate()->factory()->heap_number_map())); 354344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(not_equal, &slow); 354444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 354544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // The WebGL specification leaves the behavior of storing NaN and 354644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // +/-Infinity into integer arrays basically undefined. For more 354744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // reproducible behavior, convert these to zero. 354844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); 354944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // edi: base pointer of external storage 3550589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 355144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); 355269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ fstp_s(Operand(edi, ecx, times_2, 0)); 355344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ ret(0); 3554589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 3555257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); 355669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ fstp_d(Operand(edi, ecx, times_4, 0)); 3557257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ret(0); 355844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 355944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Perform float-to-int conversion with truncation (round-to-zero) 356044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // behavior. 356144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 356244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // For the moment we make the slow call to the runtime on 356344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // processors that don't support SSE2. The code in IntegerConvert 356444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // (code-stubs-ia32.cc) is roughly what is needed here though the 356544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // conversion failure case does not need to be handled. 35668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CpuFeatures::IsSupported(SSE2)) { 3567589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind != EXTERNAL_INT_ELEMENTS && 3568589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch elements_kind != EXTERNAL_UNSIGNED_INT_ELEMENTS) { 35698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(CpuFeatures::IsSupported(SSE2)); 35701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CpuFeatures::Scope scope(SSE2); 357169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cvttsd2si(ebx, FieldOperand(eax, HeapNumber::kValueOffset)); 357244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // ecx: untagged integer value 35733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3574589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 357569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ ClampUint8(ebx); 357669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Fall through. 3577589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 3578589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 357969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ SmiUntag(ecx); 358069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov_b(Operand(edi, ecx, times_1, 0), ebx); 358144f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3582589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 3583589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 358469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov_w(Operand(edi, ecx, times_1, 0), ebx); 358544f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 358644f0eee88ff00398ff7f715fab053374d808c90dSteve Block default: 358744f0eee88ff00398ff7f715fab053374d808c90dSteve Block UNREACHABLE(); 358844f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 358944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 359044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 35918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CpuFeatures::IsSupported(SSE3)) { 359244f0eee88ff00398ff7f715fab053374d808c90dSteve Block CpuFeatures::Scope scope(SSE3); 359344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // fisttp stores values as signed integers. To represent the 359444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // entire range of int and unsigned int arrays, store as a 359544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // 64-bit int and discard the high 32 bits. 359644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // If the value is NaN or +/-infinity, the result is 0x80000000, 359744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // which is automatically zero when taken mod 2^n, n < 32. 359844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); 35993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(esp, Immediate(2 * kPointerSize)); 360044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ fisttp_d(Operand(esp, 0)); 360169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ pop(ebx); 36023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(esp, Immediate(kPointerSize)); 360344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 36048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(CpuFeatures::IsSupported(SSE2)); 360544f0eee88ff00398ff7f715fab053374d808c90dSteve Block CpuFeatures::Scope scope(SSE2); 360644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // We can easily implement the correct rounding behavior for the 360744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // range [0, 2^31-1]. For the time being, to keep this code simple, 360844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // make the slow runtime call for values outside this range. 360944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Note: we could do better for signed int arrays. 361044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); 361144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // We will need the key if we have to make the slow runtime call. 361269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ push(ebx); 361369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ LoadPowerOf2(xmm1, ebx, 31); 361469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ pop(ebx); 361544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ ucomisd(xmm1, xmm0); 361644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(above_equal, &slow); 361769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cvttsd2si(ebx, Operand(xmm0)); 361844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 361969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // ebx: untagged integer value 362069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov(Operand(edi, ecx, times_2, 0), ebx); 36211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 362244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ ret(0); // Return original value. 36231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 36241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 36251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 36261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Slow case: call runtime. 36281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&slow); 3629257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Counters* counters = masm->isolate()->counters(); 3630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->keyed_store_external_array_slow(), 1); 3631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 36321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------- S t a t e ------------- 36331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- eax : value 36341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- ecx : key 36351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- edx : receiver 36361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- esp[0] : return address 36371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 36381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow(); 3640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(ic, RelocInfo::CODE_TARGET); 3641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- eax : value 3644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ecx : key 3645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- edx : receiver 3646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- esp[0] : return address 3647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 3650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> miss_ic = 3651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 3652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(miss_ic, RelocInfo::CODE_TARGET); 3653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) { 3657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- eax : key 3659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- edx : receiver 3660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- esp[0] : return address 3661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss_force_generic; 3663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 3665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 3666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is a smi. 36683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(eax, &miss_force_generic); 3669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the elements array. 3671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); 3672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AssertFastElements(ecx); 3673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is within bounds. 3675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); 3676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above_equal, &miss_force_generic); 3677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the result and make sure it's not the hole. 3679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(ebx, Operand(ecx, eax, times_2, 3680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FixedArray::kHeaderSize - kHeapObjectTag)); 3681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(ebx, masm->isolate()->factory()->the_hole_value()); 3682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &miss_force_generic); 3683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(eax, ebx); 3684257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ret(0); 3685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 3687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> miss_ic = 3688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 3689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(miss_ic, RelocInfo::CODE_TARGET); 3690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 36933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastDoubleElement( 36943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MacroAssembler* masm) { 36953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------- S t a t e ------------- 36963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- eax : key 36973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- edx : receiver 36983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- esp[0] : return address 36993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------------------------------- 37003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label miss_force_generic, slow_allocate_heapnumber; 37013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 37033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // have been verified by the caller to not be a smi. 37043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is a smi. 37063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(eax, &miss_force_generic); 37073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Get the elements array. 37093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); 37103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ AssertFastElements(ecx); 37113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is within bounds. 37133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp(eax, FieldOperand(ecx, FixedDoubleArray::kLengthOffset)); 37143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(above_equal, &miss_force_generic); 37153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check for the hole 37173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32); 37183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp(FieldOperand(ecx, eax, times_4, offset), Immediate(kHoleNanUpper32)); 37193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(equal, &miss_force_generic); 37203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Always allocate a heap number for the result. 37223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (CpuFeatures::IsSupported(SSE2)) { 37233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CpuFeatures::Scope use_sse2(SSE2); 37243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movdbl(xmm0, FieldOperand(ecx, eax, times_4, 37253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FixedDoubleArray::kHeaderSize)); 37263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 37273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ fld_d(FieldOperand(ecx, eax, times_4, FixedDoubleArray::kHeaderSize)); 37283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 37293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ AllocateHeapNumber(ecx, ebx, edi, &slow_allocate_heapnumber); 37303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Set the value. 37313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (CpuFeatures::IsSupported(SSE2)) { 37323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CpuFeatures::Scope use_sse2(SSE2); 37333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movdbl(FieldOperand(ecx, HeapNumber::kValueOffset), xmm0); 37343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 37353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ fstp_d(FieldOperand(ecx, HeapNumber::kValueOffset)); 37363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 37373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(eax, ecx); 37383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ret(0); 37393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&slow_allocate_heapnumber); 37413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // A value was pushed on the floating point stack before the allocation, if 37423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // the allocation fails it needs to be removed. 37433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!CpuFeatures::IsSupported(SSE2)) { 37443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fstp(0); 37453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 37463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> slow_ic = 37473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_Slow(); 37483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(slow_ic, RelocInfo::CODE_TARGET); 37493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&miss_force_generic); 37513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> miss_ic = 37523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 37533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(miss_ic, RelocInfo::CODE_TARGET); 37543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 37553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastElement( 37583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler* masm, 37593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_js_array, 37603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind elements_kind, 37613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch KeyedAccessGrowMode grow_mode) { 3762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 37633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- eax : value 37643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- ecx : key 3765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- edx : receiver 3766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- esp[0] : return address 3767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 37683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label miss_force_generic, grow, slow, transition_elements_kind; 37693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label check_capacity, prepare_slow, finish_store, commit_backing_store; 3770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 3772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 3773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is a smi. 37753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(ecx, &miss_force_generic); 37761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { 37783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfNotSmi(eax, &transition_elements_kind); 37793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 37803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the elements array and make sure it is a fast element array, not 'cow'. 3782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 3783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (is_js_array) { 3784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is within bounds. 3785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis. 37863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (grow_mode == ALLOW_JSARRAY_GROWTH) { 37873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &grow); 37883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 37893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &miss_force_generic); 37903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is within bounds. 3793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis. 3794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above_equal, &miss_force_generic); 3795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 37973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(FieldOperand(edi, HeapObject::kMapOffset), 37983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(masm->isolate()->factory()->fixed_array_map())); 37993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &miss_force_generic); 38003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&finish_store); 38023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { 38033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ecx is a smi, use times_half_pointer_size instead of 38043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // times_pointer_size 38053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(edi, 38063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ecx, 38073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch times_half_pointer_size, 38083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArray::kHeaderSize), eax); 38093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 38103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(elements_kind == FAST_ELEMENTS); 38113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Do the store and update the write barrier. 38123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ecx is a smi, use times_half_pointer_size instead of 38133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // times_pointer_size 38143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lea(ecx, FieldOperand(edi, 38153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ecx, 38163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch times_half_pointer_size, 38173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArray::kHeaderSize)); 38183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(Operand(ecx, 0), eax); 38193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure to preserve the value in register eax. 38203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ebx, eax); 38213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWrite(edi, ecx, ebx, kDontSaveFPRegs); 38223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Done. 3825257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ret(0); 38261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Handle store cache miss, replacing the ic with the generic stub. 3828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 3829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic_force_generic = 3830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 3831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); 38323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Handle transition to other elements kinds without using the generic stub. 38343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&transition_elements_kind); 38353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); 38363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(ic_miss, RelocInfo::CODE_TARGET); 38373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) { 38393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Handle transition requiring the array to grow. 38403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&grow); 38413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure the array is only growing by a single element, anything else 38433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // must be handled by the runtime. Flags are already set by previous 38443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // compare. 38453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &miss_force_generic); 38463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for the empty array, and preallocate a small backing store if 38483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // possible. 38493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 38503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(edi, Immediate(masm->isolate()->factory()->empty_fixed_array())); 38513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &check_capacity); 38523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int size = FixedArray::SizeFor(JSArray::kPreallocatedArrayElements); 38543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(size, edi, ebx, ecx, &prepare_slow, TAG_OBJECT); 38553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Restore the key, which is known to be the array length. 38563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // eax: value 38583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ecx: key 38593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // edx: receiver 38603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // edi: elements 38613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure that the backing store can hold additional elements. 38623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(edi, JSObject::kMapOffset), 38633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(masm->isolate()->factory()->fixed_array_map())); 38643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(edi, FixedArray::kLengthOffset), 38653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(Smi::FromInt(JSArray::kPreallocatedArrayElements))); 38663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ebx, Immediate(masm->isolate()->factory()->the_hole_value())); 38673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 1; i < JSArray::kPreallocatedArrayElements; ++i) { 38683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(edi, FixedArray::SizeFor(i)), ebx); 38693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 38703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the element at index zero. 38723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(edi, FixedArray::SizeFor(0)), eax); 38733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Install the new backing store in the JSArray. 38753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(edx, JSObject::kElementsOffset), edi); 38763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(edx, JSObject::kElementsOffset, edi, ebx, 38773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 38783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Increment the length of the array. 38803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(edx, JSArray::kLengthOffset), 38813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(Smi::FromInt(1))); 38823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ret(0); 38833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&check_capacity); 38853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(FieldOperand(edi, HeapObject::kMapOffset), 38863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(masm->isolate()->factory()->fixed_cow_array_map())); 38873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, &miss_force_generic); 38883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // eax: value 38903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ecx: key 38913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // edx: receiver 38923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // edi: elements 38933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure that the backing store can hold additional elements. 38943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); 38953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &slow); 38963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Grow the array and finish the store. 38983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(FieldOperand(edx, JSArray::kLengthOffset), 38993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(Smi::FromInt(1))); 39003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&finish_store); 39013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&prepare_slow); 39033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Restore the key, which is known to be the array length. 39043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ecx, Immediate(0)); 39053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&slow); 39073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow(); 39083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(ic_slow, RelocInfo::CODE_TARGET); 39093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 39101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 39111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 39121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 39133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( 39143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MacroAssembler* masm, 39153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_js_array, 39163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch KeyedAccessGrowMode grow_mode) { 39173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------- S t a t e ------------- 39183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- eax : value 39193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- ecx : key 39203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- edx : receiver 39213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- esp[0] : return address 39223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------------------------------- 39233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label miss_force_generic, transition_elements_kind, grow, slow; 39243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label check_capacity, prepare_slow, finish_store, commit_backing_store; 39253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 39263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 39273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // have been verified by the caller to not be a smi. 39283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 39293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is a smi. 39303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(ecx, &miss_force_generic); 39313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 39323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Get the elements array. 39333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 39343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ AssertFastElements(edi); 39353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 39363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (is_js_array) { 39373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is within bounds. 39383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis. 39393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (grow_mode == ALLOW_JSARRAY_GROWTH) { 39403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &grow); 39413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 39423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &miss_force_generic); 39433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 39443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 39453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is within bounds. 39463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis. 39473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &miss_force_generic); 394885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch } 394985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 39503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&finish_store); 39513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ StoreNumberToDoubleElements(eax, edi, ecx, edx, xmm0, 39523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &transition_elements_kind, true); 39533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ret(0); 39543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 39553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Handle store cache miss, replacing the ic with the generic stub. 39563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&miss_force_generic); 39573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> ic_force_generic = 39583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 39593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); 39603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Handle transition to other elements kinds without using the generic stub. 39623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&transition_elements_kind); 39633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); 39643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(ic_miss, RelocInfo::CODE_TARGET); 39653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) { 39673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Handle transition requiring the array to grow. 39683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&grow); 39693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure the array is only growing by a single element, anything else 39713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // must be handled by the runtime. Flags are already set by previous 39723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // compare. 39733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &miss_force_generic); 39743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Transition on values that can't be stored in a FixedDoubleArray. 39763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label value_is_smi; 39773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(eax, &value_is_smi); 39783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 39793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(Handle<Map>(masm->isolate()->heap()->heap_number_map()))); 39803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &transition_elements_kind); 39813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&value_is_smi); 39823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for the empty array, and preallocate a small backing store if 39843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // possible. 39853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 39863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(edi, Immediate(masm->isolate()->factory()->empty_fixed_array())); 39873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &check_capacity); 39883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int size = FixedDoubleArray::SizeFor(JSArray::kPreallocatedArrayElements); 39903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(size, edi, ebx, ecx, &prepare_slow, TAG_OBJECT); 39913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Restore the key, which is known to be the array length. 39923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ecx, Immediate(0)); 39933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // eax: value 39953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ecx: key 39963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // edx: receiver 39973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // edi: elements 39983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Initialize the new FixedDoubleArray. Leave elements unitialized for 39993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // efficiency, they are guaranteed to be initialized before use. 40003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(edi, JSObject::kMapOffset), 40013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(masm->isolate()->factory()->fixed_double_array_map())); 40023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(edi, FixedDoubleArray::kLengthOffset), 40033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(Smi::FromInt(JSArray::kPreallocatedArrayElements))); 40043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Install the new backing store in the JSArray. 40063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(edx, JSObject::kElementsOffset), edi); 40073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(edx, JSObject::kElementsOffset, edi, ebx, 40083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 40093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Increment the length of the array. 40113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(FieldOperand(edx, JSArray::kLengthOffset), 40123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(Smi::FromInt(1))); 40133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 40143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&finish_store); 40153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&check_capacity); 40173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // eax: value 40183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ecx: key 40193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // edx: receiver 40203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // edi: elements 40213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure that the backing store can hold additional elements. 40223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(ecx, FieldOperand(edi, FixedDoubleArray::kLengthOffset)); 40233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &slow); 40243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Grow the array and finish the store. 40263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(FieldOperand(edx, JSArray::kLengthOffset), 40273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(Smi::FromInt(1))); 40283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&finish_store); 40293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&prepare_slow); 40313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Restore the key, which is known to be the array length. 40323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ecx, Immediate(0)); 40333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&slow); 40353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow(); 40363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(ic_slow, RelocInfo::CODE_TARGET); 40373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 40383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 40393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 40403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 4042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 4044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 4045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_IA32 4046