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. 7498f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS 7508f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch : REQUIRE_EXACT_MAP; 7513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(receiver_reg, Handle<Map>(object->map()), 7528f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch miss_label, DO_SMI_CHECK, mode); 753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform global security token check if needed. 755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsJSGlobalProxy()) { 756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); 757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stub never generated for non-global objects that require access 760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks. 761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform map transition for the receiver if necessary. 7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) { 765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The properties must be extended before we can store the value. 766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We jump to a runtime call that extends the properties array. 767402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(scratch); // Return address. 768402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(receiver_reg); 7693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(Immediate(transition)); 770402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(eax); 771402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(scratch); 7726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference( 77344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), 77444f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm->isolate()), 77544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3, 77644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1); 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!transition.is_null()) { 781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update the map of the object; no write barrier updating is 782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // needed because the map is never in new space. 783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset), 7843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(transition)); 785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust for the number of properties stored in the object. Even in the 788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // face of a transition we can use the old map here because the size of the 789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object and the number of in-object properties is not going to change. 790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block index -= object->map()->inobject_properties(); 791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (index < 0) { 793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the property straight into the object. 794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = object->map()->instance_size() + (index * kPointerSize); 795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(FieldOperand(receiver_reg, offset), eax); 796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update the write barrier for the array address. 798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pass the value being stored in the now unused name_reg. 7993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(name_reg, eax); 8003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(receiver_reg, 8013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch offset, 8023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name_reg, 8033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 8043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs); 805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Write to the properties array. 807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = index * kPointerSize + FixedArray::kHeaderSize; 808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the properties array (optimistically). 809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); 810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(FieldOperand(scratch, offset), eax); 811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update the write barrier for the array address. 813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pass the value being stored in the now unused name_reg. 8143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(name_reg, eax); 8153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(scratch, 8163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch offset, 8173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name_reg, 8183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver_reg, 8193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs); 820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the value (register eax). 823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Generate code to check that a global property cell is empty. Create 8286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// the property cell at compilation time if no cell exists for the 8296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// property. 8303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateCheckPropertyCell(MacroAssembler* masm, 8313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject> global, 8323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 8333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 8343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 8353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell = 8363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GlobalObject::EnsurePropertyCell(global, name); 8376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(cell->value()->IsTheHole()); 8383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Oddball> the_hole = masm->isolate()->factory()->the_hole_value(); 839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (Serializer::enabled()) { 8403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(scratch, Immediate(cell)); 841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), 8423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(the_hole)); 843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 8443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(Operand::Cell(cell), Immediate(the_hole)); 845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 846257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, miss); 8476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 8486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8508defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Calls GenerateCheckPropertyCell for each global object in the prototype chain 8518defd9ff6930b4e24729971a61cf7469daf119beSteve Block// from object to (but not including) holder. 8523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateCheckPropertyCells(MacroAssembler* masm, 8533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 8543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 8553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 8563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 8573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 8583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> current = object; 8593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch while (!current.is_identical_to(holder)) { 8608defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (current->IsGlobalObject()) { 8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateCheckPropertyCell(masm, 8623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject>::cast(current), 8633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, 8643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 8653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch miss); 8668defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 8673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); 8688defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 8698defd9ff6930b4e24729971a61cf7469daf119beSteve Block} 8708defd9ff6930b4e24729971a61cf7469daf119beSteve Block 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm()) 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8753ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochRegister StubCompiler::CheckPrototypes(Handle<JSObject> object, 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register object_reg, 8773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register holder_reg, 8793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch1, 8803bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch2, 8813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 8828defd9ff6930b4e24729971a61cf7469daf119beSteve Block int save_at_depth, 8833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* miss) { 8848defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Make sure there's no overlap between holder and object registers. 8853bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 8863bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) 8873bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch && !scratch2.is(scratch1)); 88844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 8898defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Keep track of the current object in register reg. 8908defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register reg = object_reg; 8913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> current = object; 8928defd9ff6930b4e24729971a61cf7469daf119beSteve Block int depth = 0; 8938defd9ff6930b4e24729971a61cf7469daf119beSteve Block 8948defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (save_at_depth == depth) { 8958defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(Operand(esp, kPointerSize), reg); 8968defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8988defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Traverse the prototype chain and check the maps in the prototype chain for 8998defd9ff6930b4e24729971a61cf7469daf119beSteve Block // fast and global objects or do negative lookup for normal objects. 9003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch while (!current.is_identical_to(holder)) { 9013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ++depth; 9028defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9038defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Only global objects and objects that do not require access 9048defd9ff6930b4e24729971a61cf7469daf119beSteve Block // checks are allowed in stubs. 9058defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); 9068defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> prototype(JSObject::cast(current->GetPrototype())); 9088defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (!current->HasFastProperties() && 9098defd9ff6930b4e24729971a61cf7469daf119beSteve Block !current->IsJSGlobalObject() && 9108defd9ff6930b4e24729971a61cf7469daf119beSteve Block !current->IsJSGlobalProxy()) { 9118defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (!name->IsSymbol()) { 9123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name = factory()->LookupSymbol(name); 9138defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 9143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(current->property_dictionary()->FindEntry(*name) == 9158defd9ff6930b4e24729971a61cf7469daf119beSteve Block StringDictionary::kNotFound); 9168defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateDictionaryNegativeLookup(masm(), miss, reg, name, 9183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, scratch2); 919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 9203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); 9213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch reg = holder_reg; // From now on the object will be in holder_reg. 9223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); 9233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 9243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool in_new_space = heap()->InNewSpace(*prototype); 9253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> current_map(current->map()); 9263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (in_new_space) { 9273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Save the map in scratch1 for later. 9283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); 9298defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 9303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK, 9313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ALLOW_ELEMENT_TRANSITION_MAPS); 9323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check access rights to the global object. This has to happen after 9343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the map check so that we know that the object is actually a global 9353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // object. 9368defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (current->IsJSGlobalProxy()) { 9373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckAccessGlobalProxy(reg, scratch2, miss); 9383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 9393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch reg = holder_reg; // From now on the object will be in holder_reg. 9403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (in_new_space) { 9423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The prototype is in new space; we cannot store a reference to it 9433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // in the code. Load it from the map. 9443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); 9453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 9463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The prototype is in old space; load it directly. 9473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(reg, prototype); 948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 9508defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9518defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (save_at_depth == depth) { 9528defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(Operand(esp, kPointerSize), reg); 9538defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 9548defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9558defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Go to the next object in the prototype chain. 9568defd9ff6930b4e24729971a61cf7469daf119beSteve Block current = prototype; 957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 9583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(current.is_identical_to(holder)); 9598defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9608defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Log the check depth. 96144f0eee88ff00398ff7f715fab053374d808c90dSteve Block LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); 9628defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9638defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Check the holder map. 9643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(reg, Handle<Map>(holder->map()), 9653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch miss, DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); 9668defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9678defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Perform security check for access to the global object. 9688defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); 9698defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (holder->IsJSGlobalProxy()) { 9703bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ CheckAccessGlobalProxy(reg, scratch1, miss); 9713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 9723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If we've skipped any global objects, it's not enough to verify that 9743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // their maps haven't changed. We also need to check that the property 9753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // cell for the property is still empty. 9763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); 977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 978402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Return the register containing the holder. 9798defd9ff6930b4e24729971a61cf7469daf119beSteve Block return reg; 980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadField(Handle<JSObject> object, 9843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 9883bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index, 9903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 9933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(receiver, miss); 994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the prototype chain. 9963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register reg = CheckPrototypes( 9973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch object, receiver, holder, scratch1, scratch2, scratch3, name, miss); 998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the value from the properties. 1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateFastPropertyLoad(masm(), eax, reg, holder, index); 1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadCallback(Handle<JSObject> object, 10063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 10073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver, 10083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register name_reg, 10093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 10103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch2, 10113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch3, 10123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback, 10133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 10143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 10163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(receiver, miss); 1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 10193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register reg = CheckPrototypes(object, receiver, holder, scratch1, 10203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch2, scratch3, name, miss); 1021d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 10228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Insert additional parameters into the stack frame above return address. 10238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ASSERT(!scratch3.is(reg)); 10248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ pop(scratch3); // Get return address to place it below. 10258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(receiver); // receiver 10273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(scratch2, esp); 10288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ASSERT(!scratch2.is(reg)); 1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(reg); // holder 10309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Push data from AccessorInfo. 10313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (isolate()->heap()->InNewSpace(callback->data())) { 10323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(scratch1, Immediate(callback)); 10338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset)); 10349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } else { 10353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(Immediate(Handle<Object>(callback->data()))); 10369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 10378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1038d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Save a pointer to where we pushed the arguments pointer. 10396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // This will be passed as the const AccessorInfo& to the C++ callback. 10408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(scratch2); 10418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 10428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(name_reg); // name 10438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(ebx, esp); // esp points to reference to name (handler). 10448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 10458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(scratch3); // Restore return address. 1046d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 10473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 3 elements array for v8::Arguments::values_, handler for name and pointer 10488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // to the values (it considered as smi in GC). 10498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const int kStackSpace = 5; 10508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const int kApiArgc = 2; 10518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 10523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ PrepareCallApiFunction(kApiArgc); 10538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(ApiParameterOperand(0), ebx); // name. 10543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(ebx, Immediate(kPointerSize)); 10558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(ApiParameterOperand(1), ebx); // arguments pointer. 10568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1057e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emitting a stub call may try to allocate (if the code is not 1058e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // already generated). Do not allow the assembler to perform a 1059e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // garbage collection but instead return the allocation failure 1060e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // object. 10613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Address getter_address = v8::ToCData<Address>(callback->getter()); 10623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallApiFunctionAndReturn(getter_address, kStackSpace); 1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadConstant(Handle<JSObject> object, 10673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 10713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 10723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> value, 10733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 10763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(receiver, miss); 1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 10793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes( 10803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch object, receiver, holder, scratch1, scratch2, scratch3, name, miss); 1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the constant value. 10833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(eax, value); 1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object, 10893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> interceptor_holder, 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupResult* lookup, 1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register name_reg, 1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 10953bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 10963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 10987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(interceptor_holder->HasNamedInterceptor()); 10997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); 11007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the receiver isn't a smi. 11023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(receiver, miss); 11037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // So far the most popular follow ups for interceptor loads are FIELD 11057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // and CALLBACKS, so inline only them, other cases may be added 11067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // later. 11077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch bool compile_followup_inline = false; 11083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (lookup->IsFound() && lookup->IsCacheable()) { 11097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (lookup->type() == FIELD) { 11107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch compile_followup_inline = true; 11117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else if (lookup->type() == CALLBACKS && 11123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lookup->GetCallbackObject()->IsAccessorInfo()) { 11133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch compile_followup_inline = 11143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL; 11157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 11167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 11177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (compile_followup_inline) { 11197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Compile the interceptor call, followed by inline code to load the 11207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // property from further up the prototype chain if the call fails. 11217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps haven't changed. 11227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, 11233bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch1, scratch2, scratch3, 11243bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch name, miss); 11257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1)); 11267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11275710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch // Preserve the receiver register explicitly whenever it is different from 11285710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch // the holder and it is needed should the interceptor return without any 11295710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch // result. The CALLBACKS case needs the receiver to be passed into C++ code, 11305710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch // the FIELD case might cause a miss during the prototype check. 11315710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder(); 11325710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch bool must_preserve_receiver_reg = !receiver.is(holder_reg) && 11335710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch (lookup->type() == CALLBACKS || must_perfrom_prototype_check); 11345710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch 11357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Save necessary data before invoking an interceptor. 11367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Requires a frame to make GC aware of pushed pointers. 11373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 11383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope frame_scope(masm(), StackFrame::INTERNAL); 11397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11405710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch if (must_preserve_receiver_reg) { 11413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(receiver); 11423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 11433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(holder_reg); 11443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(name_reg); 1145592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 11463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Invoke an interceptor. Note: map checks from receiver to 11473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // interceptor's holder has been compiled before (see a caller 11483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // of this method.) 11493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompileCallLoadPropertyWithInterceptor(masm(), 11503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver, 11513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch holder_reg, 11523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name_reg, 11533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch interceptor_holder); 11543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 11553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if interceptor provided a value for property. If it's 11563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the case, return immediately. 11573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label interceptor_failed; 11583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(eax, factory()->no_interceptor_result_sentinel()); 11593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, &interceptor_failed); 11603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch frame_scope.GenerateLeaveFrame(); 11613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ret(0); 11627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11635710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch // Clobber registers when generating debug-code to provoke errors. 11643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&interceptor_failed); 11655710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch if (FLAG_debug_code) { 11665710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch __ mov(receiver, Immediate(BitCast<int32_t>(kZapValue))); 11675710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch __ mov(holder_reg, Immediate(BitCast<int32_t>(kZapValue))); 11685710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch __ mov(name_reg, Immediate(BitCast<int32_t>(kZapValue))); 11695710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch } 11705710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch 11713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(name_reg); 11723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(holder_reg); 11735710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch if (must_preserve_receiver_reg) { 11743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(receiver); 11753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 11763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 11773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Leave the internal frame. 11783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 117985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 11807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps from interceptor's holder to lookup's holder 11817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // haven't changed. And load lookup's holder into holder_reg. 11825710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch if (must_perfrom_prototype_check) { 11837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch holder_reg = CheckPrototypes(interceptor_holder, 11847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch holder_reg, 11853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(lookup->holder()), 11867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch1, 11877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch2, 11883bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch3, 11897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch name, 11907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch miss); 11917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 11927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (lookup->type() == FIELD) { 11947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // We found FIELD property in prototype chain of interceptor's holder. 11957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Retrieve a field from field's holder. 11967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateFastPropertyLoad(masm(), eax, holder_reg, 11973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(lookup->holder()), 11983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lookup->GetFieldIndex()); 11997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ ret(0); 12007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 12017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // We found CALLBACKS property in prototype chain of interceptor's 12027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // holder. 12037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(lookup->type() == CALLBACKS); 12043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback( 12053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AccessorInfo::cast(lookup->GetCallbackObject())); 12067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(callback->getter() != NULL); 12077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Tail call to runtime. 12097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Important invariant in CALLBACKS case: the code above must be 12107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // structured to never clobber |receiver| register. 12117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(scratch2); // return address 12127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(receiver); 12137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(holder_reg); 12143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(holder_reg, Immediate(callback)); 12157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset)); 12168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(holder_reg); 12177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(name_reg); 12187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(scratch2); // restore return address 12197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ExternalReference ref = 122144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kLoadCallbackProperty), 122244f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm()->isolate()); 12237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ TailCallExternalReference(ref, 5, 1); 12247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 12257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { // !compile_followup_inline 12267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Call the runtime system to load the interceptor. 12277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps haven't changed. 12287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register holder_reg = 12297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch CheckPrototypes(object, receiver, interceptor_holder, 12303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch1, scratch2, scratch3, name, miss); 12317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(scratch2); // save old return address 12327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch PushInterceptorArguments(masm(), receiver, holder_reg, 12337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch name_reg, interceptor_holder); 12347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(scratch2); // restore old return address 12357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 123644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference ref = 123744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), 123844f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()); 12397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ TailCallExternalReference(ref, 5, 1); 12407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { 12457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (kind_ == Code::KEYED_CALL_IC) { 12463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(ecx, Immediate(name)); 1247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, miss); 12487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 12497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 12507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object, 12533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 12543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 125559151504615d929945dc59db37bf1166937748c6Steve Block Label* miss) { 125659151504615d929945dc59db37bf1166937748c6Steve Block ASSERT(holder->IsGlobalObject()); 125759151504615d929945dc59db37bf1166937748c6Steve Block 125859151504615d929945dc59db37bf1166937748c6Steve Block // Get the number of arguments. 125959151504615d929945dc59db37bf1166937748c6Steve Block const int argc = arguments().immediate(); 126059151504615d929945dc59db37bf1166937748c6Steve Block 126159151504615d929945dc59db37bf1166937748c6Steve Block // Get the receiver from the stack. 126259151504615d929945dc59db37bf1166937748c6Steve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 126359151504615d929945dc59db37bf1166937748c6Steve Block 126459151504615d929945dc59db37bf1166937748c6Steve Block 126559151504615d929945dc59db37bf1166937748c6Steve Block // Check that the maps haven't changed. 12663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(edx, miss); 126759151504615d929945dc59db37bf1166937748c6Steve Block CheckPrototypes(object, edx, holder, ebx, eax, edi, name, miss); 126859151504615d929945dc59db37bf1166937748c6Steve Block} 126959151504615d929945dc59db37bf1166937748c6Steve Block 127059151504615d929945dc59db37bf1166937748c6Steve Block 12713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateLoadFunctionFromCell( 12723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 12733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 12743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 127559151504615d929945dc59db37bf1166937748c6Steve Block // Get the value from the cell. 1276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (Serializer::enabled()) { 12773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(edi, Immediate(cell)); 1278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); 1279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 12803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(edi, Operand::Cell(cell)); 1281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 128259151504615d929945dc59db37bf1166937748c6Steve Block 128359151504615d929945dc59db37bf1166937748c6Steve Block // Check that the cell contains the same function. 12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (isolate()->heap()->InNewSpace(*function)) { 128559151504615d929945dc59db37bf1166937748c6Steve Block // We can't embed a pointer to a function in new space so we have 128659151504615d929945dc59db37bf1166937748c6Steve Block // to verify that the shared function info is unchanged. This has 128759151504615d929945dc59db37bf1166937748c6Steve Block // the nice side effect that multiple closures based on the same 128859151504615d929945dc59db37bf1166937748c6Steve Block // function can all use this call IC. Before we load through the 128959151504615d929945dc59db37bf1166937748c6Steve Block // function, we have to verify that it still is a function. 12903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edi, miss); 129159151504615d929945dc59db37bf1166937748c6Steve Block __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); 1292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, miss); 129359151504615d929945dc59db37bf1166937748c6Steve Block 129459151504615d929945dc59db37bf1166937748c6Steve Block // Check the shared function info. Make sure it hasn't changed. 129559151504615d929945dc59db37bf1166937748c6Steve Block __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), 129659151504615d929945dc59db37bf1166937748c6Steve Block Immediate(Handle<SharedFunctionInfo>(function->shared()))); 129759151504615d929945dc59db37bf1166937748c6Steve Block } else { 12983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(edi, Immediate(function)); 129959151504615d929945dc59db37bf1166937748c6Steve Block } 13003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, miss); 130159151504615d929945dc59db37bf1166937748c6Steve Block} 130259151504615d929945dc59db37bf1166937748c6Steve Block 130359151504615d929945dc59db37bf1166937748c6Steve Block 13043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateMissBranch() { 13053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = 130644f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), 1307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch kind_, 13083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch extra_state_); 13093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(code, RelocInfo::CODE_TARGET); 13107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 13117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13133ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, 13143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 13153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int index, 13163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1318e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 1319e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 1320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1321e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 1322e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateNameCheck(name, &miss); 13277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver from the stack. 1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 13333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &miss); 1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do the right check and compute the holder register. 13363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register reg = CheckPrototypes(object, edx, holder, ebx, eax, edi, 13373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch name, &miss); 1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateFastPropertyLoad(masm(), edi, reg, holder, index); 1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the function really is a function. 13423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edi, &miss); 1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); 1344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack with the global proxy if 1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // necessary. 1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsGlobalObject()) { 1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the function. 13543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 1355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 1356257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 1357257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, 1358257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), call_kind); 1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 13623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(FIELD, name); 1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13693ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPushCall( 13703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 13713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 13723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 13733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 13743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 13756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 13766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : name 13776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[0] : return address 13786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[(argc - n) * 4] : arg[n] (zero-based) 13796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ... 13806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[(argc + 1) * 4] : receiver 13816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 13826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // If object is not an array, bail out to regular call. 13843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSArray() || !cell.is_null()) { 13853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Handle<Code>::null(); 138644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 13876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss; 13896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateNameCheck(name, &miss); 13917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the receiver from the stack. 13936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int argc = arguments().immediate(); 13946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 13956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the receiver isn't a smi. 13973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &miss); 13986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, 14003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 14016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (argc == 0) { 14036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Noop, return the length. 14046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); 14056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret((argc + 1) * kPointerSize); 14066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 1407756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label call_builtin; 1408756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 14093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (argc == 1) { // Otherwise fall through to call builtin. 14103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label attempt_to_grow_elements, with_write_barrier; 14116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the elements array of the object. 14133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(edi, FieldOperand(edx, JSArray::kElementsOffset)); 14145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 14153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that the elements are in fast mode and writable. 14163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(FieldOperand(edi, HeapObject::kMapOffset), 14173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(factory()->fixed_array_map())); 14183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &call_builtin); 14195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 14206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the array's length into eax and calculate new length. 14216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); 14226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block STATIC_ASSERT(kSmiTagSize == 1); 14236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block STATIC_ASSERT(kSmiTag == 0); 14243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(eax, Immediate(Smi::FromInt(argc))); 14256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the elements' length into ecx. 14273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); 14286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check if we could survive without allocation. 14303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(eax, ecx); 14316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(greater, &attempt_to_grow_elements); 14326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if value is a smi. 14343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ecx, Operand(esp, argc * kPointerSize)); 14353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfNotSmi(ecx, &with_write_barrier); 14363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Save new length. 14386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); 14396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the value. 14413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(edi, 14423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch eax, 14433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch times_half_pointer_size, 14443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArray::kHeaderSize - argc * kPointerSize), 14453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ecx); 144685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 14476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret((argc + 1) * kPointerSize); 14486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&with_write_barrier); 14506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); 14523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) { 14543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label fast_object, not_fast_object; 14553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastObjectElements(ebx, ¬_fast_object, Label::kNear); 14563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&fast_object); 14573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // In case of fast smi-only, convert to fast object, otherwise bail out. 14583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(¬_fast_object); 14593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastSmiOnlyElements(ebx, &call_builtin); 14603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // edi: elements array 14613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // edx: receiver 14623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ebx: map 14633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS, 14643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FAST_ELEMENTS, 14653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ebx, 14663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch edi, 14673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &call_builtin); 14683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsTransitionGenerator::GenerateSmiOnlyToObject(masm()); 14693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Restore edi. 14703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(edi, FieldOperand(edx, JSArray::kElementsOffset)); 14713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&fast_object); 14723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 14733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastObjectElements(ebx, &call_builtin); 14743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 14753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Save new length. 14773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); 14783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the value. 14803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lea(edx, FieldOperand(edi, 14813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch eax, times_half_pointer_size, 14823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArray::kHeaderSize - argc * kPointerSize)); 14833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(Operand(edx, 0), ecx); 14843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWrite(edi, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, 14863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_SMI_CHECK); 14876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret((argc + 1) * kPointerSize); 14896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&attempt_to_grow_elements); 14915913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!FLAG_inline_new) { 14925913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck __ jmp(&call_builtin); 14935913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 14945913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 14953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ebx, Operand(esp, argc * kPointerSize)); 14963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Growing elements that are SMI-only requires special handling in case 14973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the new element is non-Smi. For now, delegate to the builtin. 14983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label no_fast_elements_check; 14993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(ebx, &no_fast_elements_check); 15003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 15013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastObjectElements(ecx, &call_builtin, Label::kFar); 15023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&no_fast_elements_check); 15033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We could be lucky and the elements array could be at the top of 15053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // new-space. In this case we can just grow it in place by moving the 15063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // allocation pointer up. 15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference new_space_allocation_top = 150944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::new_space_allocation_top_address(isolate()); 15106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference new_space_allocation_limit = 151144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::new_space_allocation_limit_address(isolate()); 15126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kAllocationDelta = 4; 15146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Load top. 15156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ecx, Operand::StaticVariable(new_space_allocation_top)); 15166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check if it's the end of elements. 15183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lea(edx, FieldOperand(edi, 15196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block eax, times_half_pointer_size, 15206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FixedArray::kHeaderSize - argc * kPointerSize)); 15213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(edx, ecx); 15226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_equal, &call_builtin); 15233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(ecx, Immediate(kAllocationDelta * kPointerSize)); 15246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(ecx, Operand::StaticVariable(new_space_allocation_limit)); 15256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(above, &call_builtin); 15266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // We fit and could grow elements. 15286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(Operand::StaticVariable(new_space_allocation_top), ecx); 15296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Push the argument... 15313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(Operand(edx, 0), ebx); 15326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ... and fill the rest with holes. 15336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (int i = 1; i < kAllocationDelta; i++) { 15346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(Operand(edx, i * kPointerSize), 153544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Immediate(factory()->the_hole_value())); 15366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 15376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We know the elements array is in new space so we don't need the 15393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // remembered set, but we just pushed a value onto it so we may have to 15403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // tell the incremental marker to rescan the object that we just grew. We 15413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // don't need to worry about the holes because they are in old space and 15423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // already marked black. 15433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWrite(edi, edx, ebx, kDontSaveFPRegs, OMIT_REMEMBERED_SET); 15443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Restore receiver to edx as finish sequence assumes it's here. 15466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 15476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Increment element's and array's sizes. 15493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(FieldOperand(edi, FixedArray::kLengthOffset), 15507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Immediate(Smi::FromInt(kAllocationDelta))); 15513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // NOTE: This only happen in new-space, where we don't 15533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // care about the black-byte-count on pages. Otherwise we should 15543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // update that too if the object is black. 15553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); 15576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret((argc + 1) * kPointerSize); 15596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 15606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1561756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ bind(&call_builtin); 156244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ TailCallExternalReference( 156344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(Builtins::c_ArrayPush, isolate()), 156444f0eee88ff00398ff7f715fab053374d808c90dSteve Block argc + 1, 156544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1); 15666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 15676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss); 15693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 15706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return the generated code. 157225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen return GetCode(function); 15736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 15746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPopCall( 15773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 15783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 15793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 15803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 15813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 15826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 15836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : name 15846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[0] : return address 15856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[(argc - n) * 4] : arg[n] (zero-based) 15866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ... 15876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[(argc + 1) * 4] : receiver 15886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 15896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // If object is not an array, bail out to regular call. 15913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSArray() || !cell.is_null()) { 15923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Handle<Code>::null(); 159344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 15946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss, return_undefined, call_builtin; 15966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateNameCheck(name, &miss); 15987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 15996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the receiver from the stack. 16006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int argc = arguments().immediate(); 16016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 16026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the receiver isn't a smi. 16043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &miss); 16053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, 16063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 16076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the elements array of the object. 16096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); 16106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1611756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Check that the elements are in fast mode and writable. 16126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 161344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Immediate(factory()->fixed_array_map())); 1614756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ j(not_equal, &call_builtin); 16156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the array's length into ecx and calculate new length. 16176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ecx, FieldOperand(edx, JSArray::kLengthOffset)); 16183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(ecx, Immediate(Smi::FromInt(1))); 16196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(negative, &return_undefined); 16206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the last element. 16226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block STATIC_ASSERT(kSmiTagSize == 1); 16236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block STATIC_ASSERT(kSmiTag == 0); 16246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(eax, FieldOperand(ebx, 16256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ecx, times_half_pointer_size, 16266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FixedArray::kHeaderSize)); 16273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(eax, Immediate(factory()->the_hole_value())); 16286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(equal, &call_builtin); 16296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Set the array's length. 16316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(FieldOperand(edx, JSArray::kLengthOffset), ecx); 16326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Fill with the hole. 16346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(FieldOperand(ebx, 16356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ecx, times_half_pointer_size, 16366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FixedArray::kHeaderSize), 163744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Immediate(factory()->the_hole_value())); 16386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret((argc + 1) * kPointerSize); 16396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&return_undefined); 164144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(eax, Immediate(factory()->undefined_value())); 16426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret((argc + 1) * kPointerSize); 16436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&call_builtin); 164544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ TailCallExternalReference( 164644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(Builtins::c_ArrayPop, isolate()), 164744f0eee88ff00398ff7f715fab053374d808c90dSteve Block argc + 1, 164844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1); 16496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss); 16513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 16527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Return the generated code. 16547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch return GetCode(function); 16557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 16567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16583ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharCodeAtCall( 16593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 16603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 16613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 16623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 16633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 16647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------- S t a t e ------------- 16657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ecx : function name 16667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[0] : return address 16677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc - n) * 4] : arg[n] (zero-based) 16687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ... 16697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc + 1) * 4] : receiver 16707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------------------------------- 16717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1672756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // If object is not a string, bail out to regular call. 16733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsString() || !cell.is_null()) { 16743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Handle<Code>::null(); 167544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1676756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 16777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch const int argc = arguments().immediate(); 16787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label miss; 1680b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label name_miss; 16817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 1682b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label* index_out_of_range_label = &index_out_of_range; 16839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 1684257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (kind_ == Code::CALL_IC && 16853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (CallICBase::StringStubState::decode(extra_state_) == 1686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DEFAULT_STRING_STUB)) { 1687b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch index_out_of_range_label = &miss; 1688b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1689b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1690b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch GenerateNameCheck(name, &name_miss); 16917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps starting from the prototype haven't changed. 16937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype(masm(), 16947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Context::STRING_FUNCTION_INDEX, 16950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen eax, 16960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &miss); 16973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!object.is_identical_to(holder)); 16983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())), 16993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch eax, holder, ebx, edx, edi, name, &miss); 17007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register receiver = ebx; 17027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = edi; 17037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = eax; 17047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); 17057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (argc > 0) { 17067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); 17077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 170844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Set(index, Immediate(factory()->undefined_value())); 17097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 17107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringCharCodeAtGenerator generator(receiver, 17123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index, 17133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result, 17143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a string. 17153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a number. 17163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index_out_of_range_label, 17173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STRING_INDEX_IS_NUMBER); 17183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateFast(masm()); 17197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ ret((argc + 1) * kPointerSize); 17207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch StubRuntimeCallHelper call_helper; 17223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateSlow(masm(), call_helper); 17237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1724b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (index_out_of_range.is_linked()) { 1725b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&index_out_of_range); 172644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Set(eax, Immediate(factory()->nan_value())); 1727b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ ret((argc + 1) * kPointerSize); 1728b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 17297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&miss); 1731b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Restore function name in ecx. 17323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Set(ecx, Immediate(name)); 1733b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&name_miss); 17343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 17357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Return the generated code. 17377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch return GetCode(function); 17387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 17397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17413ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharAtCall( 17423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 17433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 17443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 17453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 17463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 17477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------- S t a t e ------------- 17487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ecx : function name 17497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[0] : return address 17507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc - n) * 4] : arg[n] (zero-based) 17517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ... 17527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc + 1) * 4] : receiver 17537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------------------------------- 17547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1755756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // If object is not a string, bail out to regular call. 17563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsString() || !cell.is_null()) { 17573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Handle<Code>::null(); 175844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1759756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 17607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch const int argc = arguments().immediate(); 17617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label miss; 1763b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label name_miss; 17647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 1765b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label* index_out_of_range_label = &index_out_of_range; 17667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (kind_ == Code::CALL_IC && 17683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (CallICBase::StringStubState::decode(extra_state_) == 1769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DEFAULT_STRING_STUB)) { 1770b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch index_out_of_range_label = &miss; 1771b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1772b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1773b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch GenerateNameCheck(name, &name_miss); 17747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps starting from the prototype haven't changed. 17767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype(masm(), 17777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Context::STRING_FUNCTION_INDEX, 17780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen eax, 17790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &miss); 17803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!object.is_identical_to(holder)); 17813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())), 17823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch eax, holder, ebx, edx, edi, name, &miss); 17837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register receiver = eax; 17857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = edi; 17863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch = edx; 17877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = eax; 17887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); 17897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (argc > 0) { 17907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); 17917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 179244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Set(index, Immediate(factory()->undefined_value())); 17937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 17947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringCharAtGenerator generator(receiver, 17963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index, 17973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 17983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result, 17993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a string. 18003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a number. 18013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index_out_of_range_label, 18023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STRING_INDEX_IS_NUMBER); 18033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateFast(masm()); 18047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ ret((argc + 1) * kPointerSize); 18057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch StubRuntimeCallHelper call_helper; 18073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateSlow(masm(), call_helper); 18087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1809b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (index_out_of_range.is_linked()) { 1810b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&index_out_of_range); 181144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Set(eax, Immediate(factory()->empty_string())); 1812b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ ret((argc + 1) * kPointerSize); 1813b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 18147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 18157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&miss); 1816b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Restore function name in ecx. 18173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Set(ecx, Immediate(name)); 1818b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&name_miss); 18193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 18206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return the generated code. 182225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen return GetCode(function); 18236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 18246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18263ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringFromCharCodeCall( 18273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 18283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 18293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 18303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 18313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 183259151504615d929945dc59db37bf1166937748c6Steve Block // ----------- S t a t e ------------- 183359151504615d929945dc59db37bf1166937748c6Steve Block // -- ecx : function name 183459151504615d929945dc59db37bf1166937748c6Steve Block // -- esp[0] : return address 183559151504615d929945dc59db37bf1166937748c6Steve Block // -- esp[(argc - n) * 4] : arg[n] (zero-based) 183659151504615d929945dc59db37bf1166937748c6Steve Block // -- ... 183759151504615d929945dc59db37bf1166937748c6Steve Block // -- esp[(argc + 1) * 4] : receiver 183859151504615d929945dc59db37bf1166937748c6Steve Block // ----------------------------------- 183959151504615d929945dc59db37bf1166937748c6Steve Block 184059151504615d929945dc59db37bf1166937748c6Steve Block const int argc = arguments().immediate(); 184159151504615d929945dc59db37bf1166937748c6Steve Block 184259151504615d929945dc59db37bf1166937748c6Steve Block // If the object is not a JSObject or we got an unexpected number of 184359151504615d929945dc59db37bf1166937748c6Steve Block // arguments, bail out to the regular call. 184444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!object->IsJSObject() || argc != 1) { 18453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Handle<Code>::null(); 184644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 184759151504615d929945dc59db37bf1166937748c6Steve Block 184859151504615d929945dc59db37bf1166937748c6Steve Block Label miss; 184959151504615d929945dc59db37bf1166937748c6Steve Block GenerateNameCheck(name, &miss); 185059151504615d929945dc59db37bf1166937748c6Steve Block 18513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (cell.is_null()) { 185259151504615d929945dc59db37bf1166937748c6Steve Block __ mov(edx, Operand(esp, 2 * kPointerSize)); 185359151504615d929945dc59db37bf1166937748c6Steve Block STATIC_ASSERT(kSmiTag == 0); 18543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &miss); 18553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, 18563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 185759151504615d929945dc59db37bf1166937748c6Steve Block } else { 18583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(cell->value() == *function); 18593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 18603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 186159151504615d929945dc59db37bf1166937748c6Steve Block GenerateLoadFunctionFromCell(cell, function, &miss); 186259151504615d929945dc59db37bf1166937748c6Steve Block } 186359151504615d929945dc59db37bf1166937748c6Steve Block 186459151504615d929945dc59db37bf1166937748c6Steve Block // Load the char code argument. 186559151504615d929945dc59db37bf1166937748c6Steve Block Register code = ebx; 186659151504615d929945dc59db37bf1166937748c6Steve Block __ mov(code, Operand(esp, 1 * kPointerSize)); 186759151504615d929945dc59db37bf1166937748c6Steve Block 186859151504615d929945dc59db37bf1166937748c6Steve Block // Check the code is a smi. 186959151504615d929945dc59db37bf1166937748c6Steve Block Label slow; 187059151504615d929945dc59db37bf1166937748c6Steve Block STATIC_ASSERT(kSmiTag == 0); 18713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(code, &slow); 187259151504615d929945dc59db37bf1166937748c6Steve Block 187359151504615d929945dc59db37bf1166937748c6Steve Block // Convert the smi code to uint16. 187459151504615d929945dc59db37bf1166937748c6Steve Block __ and_(code, Immediate(Smi::FromInt(0xffff))); 187559151504615d929945dc59db37bf1166937748c6Steve Block 18763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringCharFromCodeGenerator generator(code, eax); 18773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateFast(masm()); 187859151504615d929945dc59db37bf1166937748c6Steve Block __ ret(2 * kPointerSize); 187959151504615d929945dc59db37bf1166937748c6Steve Block 1880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch StubRuntimeCallHelper call_helper; 18813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateSlow(masm(), call_helper); 188259151504615d929945dc59db37bf1166937748c6Steve Block 188359151504615d929945dc59db37bf1166937748c6Steve Block // Tail call the full function. We do not have to patch the receiver 188459151504615d929945dc59db37bf1166937748c6Steve Block // because the function makes no use of it. 188559151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&slow); 18863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 1887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 1888257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 1889257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(function, arguments(), JUMP_FUNCTION, 1890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), call_kind); 189159151504615d929945dc59db37bf1166937748c6Steve Block 189259151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&miss); 189359151504615d929945dc59db37bf1166937748c6Steve Block // ecx: function name. 18943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 189559151504615d929945dc59db37bf1166937748c6Steve Block 189659151504615d929945dc59db37bf1166937748c6Steve Block // Return the generated code. 18973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); 189859151504615d929945dc59db37bf1166937748c6Steve Block} 189959151504615d929945dc59db37bf1166937748c6Steve Block 190059151504615d929945dc59db37bf1166937748c6Steve Block 19013ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathFloorCall( 19023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 19033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 19043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 19053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 19063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 19070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // ----------- S t a t e ------------- 19080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // -- ecx : name 19090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // -- esp[0] : return address 19100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // -- esp[(argc - n) * 4] : arg[n] (zero-based) 19110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // -- ... 19120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // -- esp[(argc + 1) * 4] : receiver 19130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // ----------------------------------- 19140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (!CpuFeatures::IsSupported(SSE2)) { 19163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Handle<Code>::null(); 191744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 191844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 19190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CpuFeatures::Scope use_sse2(SSE2); 19200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen const int argc = arguments().immediate(); 19220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // If the object is not a JSObject or we got an unexpected number of 19240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // arguments, bail out to the regular call. 192544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!object->IsJSObject() || argc != 1) { 19263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Handle<Code>::null(); 192744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 19280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label miss; 19300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen GenerateNameCheck(name, &miss); 19310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (cell.is_null()) { 19330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(edx, Operand(esp, 2 * kPointerSize)); 19340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen STATIC_ASSERT(kSmiTag == 0); 19363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &miss); 19370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, 19393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 19400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 19413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(cell->value() == *function); 19423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 19433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 19440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen GenerateLoadFunctionFromCell(cell, function, &miss); 19450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 19460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Load the (only) argument into eax. 19480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(eax, Operand(esp, 1 * kPointerSize)); 19490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Check if the argument is a smi. 19510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label smi; 19520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen STATIC_ASSERT(kSmiTag == 0); 19533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(eax, &smi); 19540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Check if the argument is a heap number and load its value into xmm0. 19560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label slow; 1957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CheckMap(eax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK); 19580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ movdbl(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); 19590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Check if the argument is strictly positive. Note this also 19610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // discards NaN. 19620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ xorpd(xmm1, xmm1); 19630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ ucomisd(xmm0, xmm1); 19640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ j(below_equal, &slow); 19650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Do a truncating conversion. 19670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ cvttsd2si(eax, Operand(xmm0)); 19680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Check if the result fits into a smi. Note this also checks for 19700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // 0x80000000 which signals a failed conversion. 19710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label wont_fit_into_smi; 19720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ test(eax, Immediate(0xc0000000)); 19730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ j(not_zero, &wont_fit_into_smi); 19740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Smi tag and return. 19760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ SmiTag(eax); 19770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&smi); 19780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ ret(2 * kPointerSize); 19790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Check if the argument is < 2^kMantissaBits. 19810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label already_round; 19820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&wont_fit_into_smi); 19830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadPowerOf2(xmm1, ebx, HeapNumber::kMantissaBits); 19840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ ucomisd(xmm0, xmm1); 19850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ j(above_equal, &already_round); 19860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Save a copy of the argument. 19880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ movaps(xmm2, xmm0); 19890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Compute (argument + 2^kMantissaBits) - 2^kMantissaBits. 19910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ addsd(xmm0, xmm1); 19920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ subsd(xmm0, xmm1); 19930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Compare the argument and the tentative result to get the right mask: 19950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // if xmm2 < xmm0: 19960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // xmm2 = 1...1 19970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // else: 19980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // xmm2 = 0...0 19990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ cmpltsd(xmm2, xmm0); 20000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 20010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Subtract 1 if the argument was less than the tentative result. 20020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadPowerOf2(xmm1, ebx, 0); 20030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ andpd(xmm1, xmm2); 20040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ subsd(xmm0, xmm1); 20050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 20060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Return a new heap number. 20070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ AllocateHeapNumber(eax, ebx, edx, &slow); 20080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); 20090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ ret(2 * kPointerSize); 20100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 20110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Return the argument (when it's an already round heap number). 20120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&already_round); 20130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ mov(eax, Operand(esp, 1 * kPointerSize)); 20140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ ret(2 * kPointerSize); 20150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 20160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Tail call the full function. We do not have to patch the receiver 20170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // because the function makes no use of it. 20180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&slow); 2019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(function, arguments(), JUMP_FUNCTION, 2020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), CALL_AS_METHOD); 20210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 20220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&miss); 20230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // ecx: function name. 20243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 20250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 20260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Return the generated code. 20273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); 20280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 20290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 20300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 20313ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathAbsCall( 20323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 20333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 20343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 20353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 20363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2037f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // ----------- S t a t e ------------- 2038f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- ecx : name 2039f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- esp[0] : return address 2040f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- esp[(argc - n) * 4] : arg[n] (zero-based) 2041f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- ... 2042f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- esp[(argc + 1) * 4] : receiver 2043f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // ----------------------------------- 2044f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2045f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch const int argc = arguments().immediate(); 2046f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2047f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // If the object is not a JSObject or we got an unexpected number of 2048f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // arguments, bail out to the regular call. 204944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!object->IsJSObject() || argc != 1) { 20503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Handle<Code>::null(); 205144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 2052f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2053f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Label miss; 2054f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch GenerateNameCheck(name, &miss); 2055f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 20563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (cell.is_null()) { 2057f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ mov(edx, Operand(esp, 2 * kPointerSize)); 2058f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2059f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch STATIC_ASSERT(kSmiTag == 0); 20603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &miss); 2061f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 20623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, 20633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 2064f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch } else { 20653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(cell->value() == *function); 20663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 20673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 2068f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch GenerateLoadFunctionFromCell(cell, function, &miss); 2069f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch } 2070f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2071f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Load the (only) argument into eax. 2072f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ mov(eax, Operand(esp, 1 * kPointerSize)); 2073f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2074f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Check if the argument is a smi. 2075f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Label not_smi; 2076f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch STATIC_ASSERT(kSmiTag == 0); 20773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(eax, ¬_smi); 2078f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2079f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0 2080f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // otherwise. 2081f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ mov(ebx, eax); 2082f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ sar(ebx, kBitsPerInt - 1); 2083f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2084f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Do bitwise not or do nothing depending on ebx. 20853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ xor_(eax, ebx); 2086f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2087f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Add 1 or do nothing depending on ebx. 20883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(eax, ebx); 2089f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2090f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // If the result is still negative, go to the slow case. 2091f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // This only happens for the most negative smi. 2092f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Label slow; 2093f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ j(negative, &slow); 2094f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2095f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Smi case done. 2096f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ ret(2 * kPointerSize); 2097f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2098f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Check if the argument is a heap number and load its exponent and 2099f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // sign into ebx. 2100f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(¬_smi); 2101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CheckMap(eax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK); 2102f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ mov(ebx, FieldOperand(eax, HeapNumber::kExponentOffset)); 2103f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2104f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Check the sign of the argument. If the argument is positive, 2105f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // just return it. 2106f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Label negative_sign; 2107f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ test(ebx, Immediate(HeapNumber::kSignMask)); 2108f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ j(not_zero, &negative_sign); 2109f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ ret(2 * kPointerSize); 2110f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2111f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // If the argument is negative, clear the sign, and return a new 2112f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // number. 2113f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(&negative_sign); 2114f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ and_(ebx, ~HeapNumber::kSignMask); 2115f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ mov(ecx, FieldOperand(eax, HeapNumber::kMantissaOffset)); 2116f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ AllocateHeapNumber(eax, edi, edx, &slow); 2117f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ebx); 2118f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); 2119f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ ret(2 * kPointerSize); 2120f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2121f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Tail call the full function. We do not have to patch the receiver 2122f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // because the function makes no use of it. 2123f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(&slow); 2124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(function, arguments(), JUMP_FUNCTION, 2125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), CALL_AS_METHOD); 2126f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2127f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(&miss); 2128f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // ecx: function name. 21293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2130f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2131f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Return the generated code. 21323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); 2133f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch} 2134f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2135f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 21363ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileFastApiCall( 213744f0eee88ff00398ff7f715fab053374d808c90dSteve Block const CallOptimization& optimization, 21383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 21393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 21403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 21413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 21423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 214344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(optimization.is_simple_api_call()); 214444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Bail out if object is a global object as we don't want to 214544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // repatch it to global receiver. 21463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (object->IsGlobalObject()) return Handle<Code>::null(); 21473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!cell.is_null()) return Handle<Code>::null(); 21483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSObject()) return Handle<Code>::null(); 214944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int depth = optimization.GetPrototypeDepthOfExpectedType( 21503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>::cast(object), holder); 21513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (depth == kInvalidProtoDepth) return Handle<Code>::null(); 215244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 215344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label miss, miss_before_stack_reserved; 215444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 215544f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenerateNameCheck(name, &miss_before_stack_reserved); 215644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 215744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Get the receiver from the stack. 215844f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int argc = arguments().immediate(); 215944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 216044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 216144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the receiver isn't a smi. 21623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &miss_before_stack_reserved); 216344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 216444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 216544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_const(), 1); 216644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_const_fast_api(), 1); 216744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 216844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Allocate space for v8::Arguments implicit values. Must be initialized 216944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // before calling any runtime function. 21703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(esp, Immediate(kFastApiCallArguments * kPointerSize)); 217144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 217244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the maps haven't changed and find a Holder as a side effect. 21733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, 21743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, depth, &miss); 217544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 217644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Move the return address on top of the stack. 217744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(eax, Operand(esp, 3 * kPointerSize)); 217844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(Operand(esp, 0 * kPointerSize), eax); 217944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 218044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains 218144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // duplicate of return address and will be overwritten. 21823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateFastApiCall(masm(), optimization, argc); 218344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 218444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&miss); 21853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); 218644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 218744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&miss_before_stack_reserved); 21883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 218944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 219044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Return the generated code. 219144f0eee88ff00398ff7f715fab053374d808c90dSteve Block return GetCode(function); 219244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 219344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 219444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 21953ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object, 21963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 21973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 21983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 21993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckType check) { 2200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2201e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 2202e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 2203e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 2204e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 2205e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 2206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 22076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 220844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (HasCustomCallGenerator(function)) { 22093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = CompileCustomCall(object, holder, 22103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell>::null(), 22113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function, name); 22123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // A null handle means bail out to the regular compiler code below. 22133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!code.is_null()) return code; 22146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 22156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 221644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label miss; 221744f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenerateNameCheck(name, &miss); 22187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver from the stack. 2220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 2221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 2222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 2224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check != NUMBER_CHECK) { 22253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &miss); 2226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure that it's okay not to patch the on stack receiver 2229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // unless we're doing a receiver map check. 2230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); 2231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (check) { 2232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case RECEIVER_MAP_CHECK: 223344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(isolate()->counters()->call_const(), 1); 2234402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 2235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 22363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, 22373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch edi, name, &miss); 2238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack with the global proxy if 2240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // necessary. 2241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsGlobalObject()) { 2242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 2243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 2244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 2246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case STRING_CHECK: 22483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (function->IsBuiltin() || !function->shared()->is_classic_mode()) { 2249e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the object is a string or a symbol. 22507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax); 2251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above_equal, &miss); 2252e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the maps starting from the prototype haven't changed. 22537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype( 22540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen masm(), Context::STRING_FUNCTION_INDEX, eax, &miss); 22553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes( 22563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(JSObject::cast(object->GetPrototype())), 22573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch eax, holder, ebx, edx, edi, name, &miss); 22583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 225985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // Calling non-strict non-builtins with a value as the receiver 226085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // requires boxing. 226185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch __ jmp(&miss); 22623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 22633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 22643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 22653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case NUMBER_CHECK: 22663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (function->IsBuiltin() || !function->shared()->is_classic_mode()) { 2267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label fast; 2268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the object is a smi or a heap number. 22693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(edx, &fast); 2270e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); 2271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&fast); 2273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the maps starting from the prototype haven't changed. 22747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype( 22750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss); 22763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes( 22773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(JSObject::cast(object->GetPrototype())), 22783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch eax, holder, ebx, edx, edi, name, &miss); 22793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 228085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // Calling non-strict non-builtins with a value as the receiver 228185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // requires boxing. 228285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch __ jmp(&miss); 22833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 22843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 22853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 22863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case BOOLEAN_CHECK: 22873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (function->IsBuiltin() || !function->shared()->is_classic_mode()) { 2288e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label fast; 2289e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the object is a boolean. 229044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(edx, factory()->true_value()); 2291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &fast); 229244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(edx, factory()->false_value()); 2293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2294e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&fast); 2295e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the maps starting from the prototype haven't changed. 22967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype( 22970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss); 22983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes( 22993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(JSObject::cast(object->GetPrototype())), 23003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch eax, holder, ebx, edx, edi, name, &miss); 23013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 23023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Calling non-strict non-builtins with a value as the receiver 23033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // requires boxing. 23043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&miss); 2305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 2307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 2311257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 2312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(function, arguments(), JUMP_FUNCTION, 2313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), call_kind); 2314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 2316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 23173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 232025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen return GetCode(function); 2321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23243ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, 23253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 23263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2328e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 2329e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 2330e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 2331e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 2332e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 2333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateNameCheck(name, &miss); 23377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the number of arguments. 2339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 2340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 2342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupPostInterceptor(holder, name, &lookup); 2343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver from the stack. 2345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 2346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallInterceptorCompiler compiler(this, arguments(), ecx, extra_state_); 23483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch compiler.Compile(masm(), object, holder, name, &lookup, edx, ebx, edi, eax, 23493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 2350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore receiver. 2352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 2353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the function really is a function. 23553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(eax, &miss); 2356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); 2357257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack with the global proxy if 2360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // necessary. 2361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsGlobalObject()) { 2362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 2363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 2364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the function. 2367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edi, eax); 23683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 2370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 2371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, 2372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), call_kind); 2373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle load cache miss. 2375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 23763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23833ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallGlobal( 23843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 23853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject> holder, 23863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 23873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 23883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2390e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 2391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 2392e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 2393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 2394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 2395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 239659151504615d929945dc59db37bf1166937748c6Steve Block 239744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (HasCustomCallGenerator(function)) { 23983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = CompileCustomCall(object, holder, cell, function, name); 23993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // A null handle means bail out to the regular compiler code below. 24003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!code.is_null()) return code; 240159151504615d929945dc59db37bf1166937748c6Steve Block } 240259151504615d929945dc59db37bf1166937748c6Steve Block 2403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 24047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateNameCheck(name, &miss); 24057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the number of arguments. 2407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 240859151504615d929945dc59db37bf1166937748c6Steve Block GenerateGlobalReceiverCheck(object, holder, name, &miss); 240959151504615d929945dc59db37bf1166937748c6Steve Block GenerateLoadFunctionFromCell(cell, function, &miss); 2410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack with the global proxy. 2412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsGlobalObject()) { 2413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 2414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 2415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the context (function already in edi). 2418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 2419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the cached code (tail call). 242144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 242244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_global_inline(), 1); 2423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount expected(function->shared()->formal_parameter_count()); 24243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 2426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 24273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We call indirectly through the code field in the function to 24283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // allow recompilation to take effect without changing any of the 24293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // call sites. 24303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), 24313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expected, arguments(), JUMP_FUNCTION, 24323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch NullCallWrapper(), call_kind); 2433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 2435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 243644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_global_inline_miss(), 1); 24373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(NORMAL, name); 2441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24443ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, 24455913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index, 24463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> transition, 24473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 2450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 24514515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- edx : receiver 2452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Generate store field code. Trashes the name register. 24573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateStoreField(masm(), object, index, transition, edx, ecx, ebx, &miss); 2458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 24613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ecx, Immediate(name)); // restore name 246244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); 2463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(ic, RelocInfo::CODE_TARGET); 2464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 24663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); 2467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24703ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreCallback( 24713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 24723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback, 24733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 2476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 24774515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- edx : receiver 2478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the object hasn't changed. 24833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(edx, Handle<Map>(object->map()), 24843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); 2485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform global security token check if needed. 2487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsJSGlobalProxy()) { 24884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CheckAccessGlobalProxy(edx, ebx, &miss); 2489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stub never generated for non-global objects that require access 2492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks. 2493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 2494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); // remove the return address 24964515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(edx); // receiver 24973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(Immediate(callback)); // callback info 2498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); // name 2499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(eax); // value 2500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); // restore return address 2501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to the runtime system. 2503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference store_callback_property = 250444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); 25056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(store_callback_property, 4, 1); 2506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 250944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); 2510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(ic, RelocInfo::CODE_TARGET); 2511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25173ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreInterceptor( 25183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 25193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 2522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 25234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- edx : receiver 2524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the object hasn't changed. 25293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(edx, Handle<Map>(receiver->map()), 25303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); 2531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform global security token check if needed. 2533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (receiver->IsJSGlobalProxy()) { 25344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CheckAccessGlobalProxy(edx, ebx, &miss); 2535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stub never generated for non-global objects that require access 2538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks. 2539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); 2540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); // remove the return address 25424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(edx); // receiver 2543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); // name 2544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(eax); // value 2545e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(Immediate(Smi::FromInt(strict_mode_))); 2546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); // restore return address 2547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to the runtime system. 2549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference store_ic_property = 255044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); 2551e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ TailCallExternalReference(store_ic_property, 4, 1); 2552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 255544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); 2556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(ic, RelocInfo::CODE_TARGET); 2557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25633ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreGlobal( 25643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject> object, 25653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 25663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 2569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 25704515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- edx : receiver 2571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the global has not changed. 25764515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ cmp(FieldOperand(edx, HeapObject::kMapOffset), 2577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(Handle<Map>(object->map()))); 2578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Compute the cell operand to use. 25813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ebx, Immediate(cell)); 25823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset); 2583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the value in the cell is not the hole. If it is, this 25851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // cell could have been deleted and reintroducing the global needs 25861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // to update the property details in the property dictionary of the 25871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // global object. We bail out to the runtime system to do that. 258844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(cell_operand, factory()->the_hole_value()); 25891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(equal, &miss); 25901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 25911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Store the value in the cell. 25921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(cell_operand, eax); 25933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // No write barrier here, because cells are always rescanned. 25941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the value (register eax). 259644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 259744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_store_global_inline(), 1); 2598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 2599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 260244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_store_global_inline_miss(), 1); 260344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); 2604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(ic, RelocInfo::CODE_TARGET); 2605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(NORMAL, name); 2608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 26113ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object, 26125913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index, 26133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> transition, 26143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 26176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : key 26186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- edx : receiver 2619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 262344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 262444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_store_field(), 1); 2625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 26273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(ecx, Immediate(name)); 2628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Generate store field code. Trashes the name register. 26313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateStoreField(masm(), object, index, transition, edx, ecx, ebx, &miss); 2632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 263544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_store_field(), 1); 263644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(ic, RelocInfo::CODE_TARGET); 2638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 26403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); 2641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 26443ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreElement( 26453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> receiver_map) { 2646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------- S t a t e ------------- 2647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- eax : value 2648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- ecx : key 2649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- edx : receiver 2650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- esp[0] : return address 2651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------------------------------- 2652589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind = receiver_map->elements_kind(); 26533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE; 26543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> stub = 26553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch KeyedStoreElementStub(is_jsarray, elements_kind, grow_mode_).GetCode(); 26563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); 2658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(ic, RelocInfo::CODE_TARGET); 2661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 26633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string()); 2664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 26673ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( 26683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MapHandleList* receiver_maps, 26693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CodeHandleList* handler_stubs, 26703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MapHandleList* transitioned_maps) { 2671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- eax : value 2673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ecx : key 2674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- edx : receiver 2675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- esp[0] : return address 2676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 26783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(edx, &miss, Label::kNear); 26793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); 26803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ebx: receiver->map(). 26813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < receiver_maps->length(); ++i) { 26823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(edi, receiver_maps->at(i)); 26833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (transitioned_maps->at(i).is_null()) { 26843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, handler_stubs->at(i)); 26853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 26863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label next_map; 26873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &next_map, Label::kNear); 26883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ebx, Immediate(transitioned_maps->at(i))); 26893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET); 26903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&next_map); 26913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&miss); 2694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(miss_ic, RelocInfo::CODE_TARGET); 2696e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2697e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Return the generated code. 26983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); 2699e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2700e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2701e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 27023ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name, 27033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 27043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> last) { 27056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 27066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- eax : receiver 27076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : name 27086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[0] : return address 27096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 27106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss; 27116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 27126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the receiver isn't a smi. 27133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(eax, &miss); 27146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 27158defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(last->IsGlobalObject() || last->HasFastProperties()); 27168defd9ff6930b4e24729971a61cf7469daf119beSteve Block 27176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check the maps of the full prototype chain. Also check that 27186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // global property cells up to (but not including) the last object 27196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // in the prototype chain are empty. 27203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss); 27216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 27226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // If the last object in the prototype chain is a global object, 27236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // check that the global property cell is empty. 27246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (last->IsGlobalObject()) { 27253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateCheckPropertyCell( 27263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm(), Handle<GlobalObject>::cast(last), name, edx, &miss); 27276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 27286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 27296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return undefined if maps of the full prototype chain are still the 27306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // same and no global property with this name contains a value. 273144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(eax, isolate()->factory()->undefined_value()); 27326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret(0); 27336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 27346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss); 27356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 27366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 27376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return the generated code. 27383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NONEXISTENT, factory()->empty_string()); 27396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 27406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27423ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object, 27433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 27445913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index, 27453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2747402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 2748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 2749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27533bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch GenerateLoadField(object, holder, eax, ebx, edx, edi, index, name, &miss); 2754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(FIELD, name); 2759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27623ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadCallback( 27633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 27643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 27653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 27663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback) { 2767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2768402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 2769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 2770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadCallback(object, holder, eax, ecx, ebx, edx, edi, callback, 27753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 2776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27843ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object, 27853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 27863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> value, 27873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2789402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 2790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 2791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27953bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch GenerateLoadConstant(object, holder, eax, ebx, edx, edi, value, name, &miss); 2796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CONSTANT_FUNCTION, name); 2801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28043ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> receiver, 28053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 28063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2808402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 2809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 2810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 2815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupPostInterceptor(holder, name, &lookup); 2816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // TODO(368): Compile in the whole chain: all the interceptors in 2818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // prototypes and ultimate answer. 28193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadInterceptor(receiver, holder, &lookup, eax, ecx, edx, ebx, edi, 28203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 2821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28303ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadGlobal( 28313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 28323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject> holder, 28333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 28343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 28353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_dont_delete) { 2836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2837402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 2838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 2839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 28443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(eax, &miss); 28453bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CheckPrototypes(object, eax, holder, ebx, edx, edi, name, &miss); 2846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the value from the cell. 2848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (Serializer::enabled()) { 28493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ebx, Immediate(cell)); 2850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); 2851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 28523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ebx, Operand::Cell(cell)); 2853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for deleted property if property can actually be deleted. 2856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!is_dont_delete) { 285744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(ebx, factory()->the_hole_value()); 2858257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &miss); 2859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (FLAG_debug_code) { 286044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(ebx, factory()->the_hole_value()); 2861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Check(not_equal, "DontDelete cells can't contain the hole"); 2862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 286444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 286544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_load_global_stub(), 1); 2866402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, ebx); 2867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 2868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 287044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_load_global_stub_miss(), 1); 2871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(NORMAL, name); 2875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28783ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name, 28793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 28803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 28815913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index) { 2882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2883402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 2884402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 2885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 288944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 289044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_field(), 1); 2891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 28933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(eax, Immediate(name)); 2894257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28963bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); 2897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 289944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_field(), 1); 2900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(FIELD, name); 2904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29073ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadCallback( 29083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 29093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 29103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 29113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback) { 2912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2913402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 2914402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 2915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 291944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 292044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_callback(), 1); 2921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 29233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(eax, Immediate(name)); 2924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadCallback(receiver, holder, edx, eax, ebx, ecx, edi, callback, 29273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 2928e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 293044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_callback(), 1); 2931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29383ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadConstant( 29393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 29403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 29413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 29423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> value) { 2943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2944402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 2945402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 2946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 295044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 295144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_constant_function(), 1); 2952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 29543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(eax, Immediate(name)); 2955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadConstant( 29583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver, holder, edx, ebx, ecx, edi, value, name, &miss); 2959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 296044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_constant_function(), 1); 2961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CONSTANT_FUNCTION, name); 2965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29683ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor( 29693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 29703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 29713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2973402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 2974402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 2975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 297944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 298044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_interceptor(), 1); 2981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 29833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(eax, Immediate(name)); 2984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 2985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 2987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupPostInterceptor(holder, name, &lookup); 29883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadInterceptor(receiver, holder, &lookup, edx, eax, ecx, ebx, edi, 29893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 2990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 299144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_interceptor(), 1); 2992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29993ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength( 30003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 3001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 3002402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 3003402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 3004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 3005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 3006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 3007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 300844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 300944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_array_length(), 1); 3010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 30123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(eax, Immediate(name)); 3013257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 3014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3015402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateLoadArrayLength(masm(), edx, ecx, &miss); 3016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 301744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_array_length(), 1); 3018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 3021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 3022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30253ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadStringLength( 30263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 3027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 3028402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 3029402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 3030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 3031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 3032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 3033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 303444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 303544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_string_length(), 1); 3036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 30383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(eax, Immediate(name)); 3039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 3040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true); 3042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 304344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_string_length(), 1); 3044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 3047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 3048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30513ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype( 30523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 3053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 3054402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 3055402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 3056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 3057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 3058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 3059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 306044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 306144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_function_prototype(), 1); 3062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 30643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(eax, Immediate(name)); 3065257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &miss); 3066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3067402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); 3068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 306944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_function_prototype(), 1); 3070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 3073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 3074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30773ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadElement( 30783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> receiver_map) { 3079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------- S t a t e ------------- 3080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- eax : key 3081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- edx : receiver 3082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- esp[0] : return address 3083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------------------------------- 30843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3085589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind = receiver_map->elements_kind(); 30863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode(); 30873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); 3089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3090257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 30933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string()); 3094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 30973ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( 30983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MapHandleList* receiver_maps, 30993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CodeHandleList* handler_ics) { 3100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- eax : key 3102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- edx : receiver 3103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- esp[0] : return address 3104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 3106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(edx, &miss); 3107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register map_reg = ebx; 3109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(map_reg, FieldOperand(edx, HeapObject::kMapOffset)); 3110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int receiver_count = receiver_maps->length(); 3111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int current = 0; current < receiver_count; ++current) { 31123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(map_reg, receiver_maps->at(current)); 31133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, handler_ics->at(current)); 3114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&miss); 3117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Return the generated code. 31203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); 3121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Specialized stub for constructing objects from functions which only have only 3125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// simple assignments of the form this.x = ...; in their body. 31263ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> ConstructStubCompiler::CompileConstructStub( 31273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function) { 3128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 3129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : argc 3130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- edi : constructor 3131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 3132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[4] : last argument 3133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 3134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label generic_stub_call; 3135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 3136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check to see whether there are any break points in the function code. If 3137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // there are jump to the generic constructor stub which calls the actual 3138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // code for the function thereby hitting the break points. 3139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 3140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kDebugInfoOffset)); 314144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(ebx, factory()->undefined_value()); 3142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &generic_stub_call); 3143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 3144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the initial map and verify that it is in fact a map. 3146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); 3147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Will both indicate a NULL and a Smi. 31483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(ebx, &generic_stub_call); 3149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpObjectType(ebx, MAP_TYPE, ecx); 3150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &generic_stub_call); 3151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 3153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cannot construct functions this way. 3154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edi: constructor 3155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ebx: initial map 3156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpInstanceType(ebx, JS_FUNCTION_TYPE); 3157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Assert(not_equal, "Function constructed by construct stub."); 3158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 3159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Now allocate the JSObject on the heap by moving the new space allocation 3161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // top forward. 3162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edi: constructor 3163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ebx: initial map 3164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset)); 3165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ shl(ecx, kPointerSizeLog2); 31663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(ecx, edx, ecx, no_reg, 31673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &generic_stub_call, NO_ALLOCATION_FLAGS); 3168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocated the JSObject, now initialize the fields and add the heap tag. 3170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ebx: initial map 3171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edx: JSObject (untagged) 3172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(edx, JSObject::kMapOffset), ebx); 317344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(ebx, factory()->empty_fixed_array()); 3174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(edx, JSObject::kPropertiesOffset), ebx); 3175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(edx, JSObject::kElementsOffset), ebx); 3176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push the allocated object to the stack. This is the object that will be 3178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // returned (after it is tagged). 3179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(edx); 3180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: argc 3182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edx: JSObject (untagged) 3183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the address of the first in-object property into edx. 3184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(edx, Operand(edx, JSObject::kHeaderSize)); 3185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the location of the first argument. The stack contains the 3186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // allocated object and the return address on top of the argc arguments. 3187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(ecx, Operand(esp, eax, times_4, 1 * kPointerSize)); 3188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use edi for holding undefined which is used in several places below. 319044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(edi, factory()->undefined_value()); 3191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: argc 3193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ecx: first argument 3194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edx: first in-object property of the JSObject 3195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edi: undefined 3196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the initialized properties with a constant value or a passed argument 3197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // depending on the this.x = ...; assignment in the function. 31983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<SharedFunctionInfo> shared(function->shared()); 3199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < shared->this_property_assignments_count(); i++) { 3200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (shared->IsThisPropertyAssignmentArgument(i)) { 3201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the argument assigned to the property is actually passed. 3202e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // If argument is not passed the property is set to undefined, 3203e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // otherwise find it on the stack. 3204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int arg_number = shared->GetThisPropertyAssignmentArgument(i); 3205e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(ebx, edi); 3206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, arg_number); 32078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CpuFeatures::IsSupported(CMOV)) { 3208e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke CpuFeatures::Scope use_cmov(CMOV); 3209e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmov(above, ebx, Operand(ecx, arg_number * -kPointerSize)); 3210e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 3211e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label not_passed; 3212e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(below_equal, ¬_passed); 3213e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(ebx, Operand(ecx, arg_number * -kPointerSize)); 3214e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(¬_passed); 3215e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 3216e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store value in the property. 3217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(edx, i * kPointerSize), ebx); 3218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 3219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the property to the constant value. 3220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i)); 3221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(edx, i * kPointerSize), Immediate(constant)); 3222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the unused in-object property fields with undefined. 32268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ASSERT(function->has_initial_map()); 3227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = shared->this_property_assignments_count(); 32288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang i < function->initial_map()->inobject_properties(); 3229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i++) { 3230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(edx, i * kPointerSize), edi); 3231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move argc to ebx and retrieve and tag the JSObject to return. 3234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, eax); 3235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(eax); 32363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ or_(eax, Immediate(kHeapObjectTag)); 3237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Remove caller arguments and receiver from the stack and return. 3239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ecx); 3240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(esp, Operand(esp, ebx, times_pointer_size, 1 * kPointerSize)); 3241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); 324244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 324344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->constructed_objects(), 1); 324444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->constructed_objects_stub(), 1); 3245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 3246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the generic stub in case the specialized code cannot handle the 3248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // construction. 3249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&generic_stub_call); 32503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = isolate()->builtins()->JSConstructStubGeneric(); 32513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(code, RelocInfo::CODE_TARGET); 3252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 3254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(); 3255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 32583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#undef __ 32593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#define __ ACCESS_MASM(masm) 32603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 32613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 32623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadDictionaryElement( 32633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MacroAssembler* masm) { 32641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------- S t a t e ------------- 32651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- eax : key 32661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- edx : receiver 32671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- esp[0] : return address 32681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 32693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label slow, miss_force_generic; 3270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 32713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 32723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // have been verified by the caller to not be a smi. 32733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(eax, &miss_force_generic); 32743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(ebx, eax); 32753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ SmiUntag(ebx); 32763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); 32771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 32783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Push receiver on the stack to free up a register for the dictionary 32793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // probing. 32803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ push(edx); 32813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ LoadFromNumberDictionary(&slow, 32823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ecx, 32833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch eax, 32843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ebx, 32853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch edx, 32863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch edi, 32873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch eax); 32883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Pop receiver before returning. 32893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ pop(edx); 32903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ret(0); 3291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 32923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&slow); 32933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ pop(edx); 3294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- eax : value 3297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ecx : key 3298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- edx : receiver 3299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- esp[0] : return address 3300257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 33023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> slow_ic = 33033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_Slow(); 33043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(slow_ic, RelocInfo::CODE_TARGET); 3305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 33063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&miss_force_generic); 33073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------- S t a t e ------------- 33083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- eax : value 33093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- ecx : key 33103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- edx : receiver 33113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- esp[0] : return address 33123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------------------------------- 3313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 33143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> miss_force_generic_ic = 33153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 33163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(miss_force_generic_ic, RelocInfo::CODE_TARGET); 33173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 3318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadExternalArray( 3321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MacroAssembler* masm, 3322589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind) { 3323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- eax : key 3325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- edx : receiver 3326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- esp[0] : return address 3327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss_force_generic, failed_allocation, slow; 3329257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 3331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 33321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the key is a smi. 33343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(eax, &miss_force_generic); 33351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the index is in range. 3337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); 333869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmp(eax, FieldOperand(ebx, ExternalArray::kLengthOffset)); 33391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Unsigned comparison catches both negative and too-large values. 3340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above_equal, &miss_force_generic); 33411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset)); 33421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ebx: base pointer of external storage 33433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3344589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 334569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ SmiUntag(eax); // Untag the index. 334669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movsx_b(eax, Operand(ebx, eax, times_1, 0)); 33471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3348589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 3349589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 335069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ SmiUntag(eax); // Untag the index. 335169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movzx_b(eax, Operand(ebx, eax, times_1, 0)); 33521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3353589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 335469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movsx_w(eax, Operand(ebx, eax, times_1, 0)); 33551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3356589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 335769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movzx_w(eax, Operand(ebx, eax, times_1, 0)); 33581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3359589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 3360589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 336169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov(ecx, Operand(ebx, eax, times_2, 0)); 33621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3363589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 336469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ fld_s(Operand(ebx, eax, times_2, 0)); 33651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3366589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 336769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ fld_d(Operand(ebx, eax, times_4, 0)); 3368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 33691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block default: 33701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 33711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 33721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 33731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For integer array types: 33751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ecx: value 33761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For floating-point array type: 33771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // FP(0): value 33781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3379589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_INT_ELEMENTS || 3380589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { 33811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For the Int and UnsignedInt array types, we need to see whether 33821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the value can be represented in a Smi. If not, we need to convert 33831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // it to a HeapNumber. 33841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label box_int; 3385589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_INT_ELEMENTS) { 33861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmp(ecx, 0xC0000000); 33871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(sign, &box_int); 33881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 3389589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind); 33901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // The test is different for unsigned int values. Since we need 33911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the value to be in the range of a positive smi, we can't 33921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // handle either of the top two bits being set in the value. 33931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ test(ecx, Immediate(0xC0000000)); 33941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(not_zero, &box_int); 33951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 33961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(eax, ecx); 33981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ SmiTag(eax); 33991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 34001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&box_int); 34021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Allocate a HeapNumber for the int and perform int-to-double 34041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // conversion. 3405589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_INT_ELEMENTS) { 34061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(ecx); 34071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ fild_s(Operand(esp, 0)); 34081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ pop(ecx); 34091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 3410589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind); 34111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Need to zero-extend the value. 34121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // There's no fild variant for unsigned values, so zero-extend 34131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // to a 64-bit int manually. 34141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(Immediate(0)); 34151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(ecx); 34161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ fild_d(Operand(esp, 0)); 34171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ pop(ecx); 34181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ pop(ecx); 34191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 34201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // FP(0): value 34211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); 34221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Set the value. 34231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(eax, ecx); 34241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 34251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 3426589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || 3427589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 34281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For the floating-point array type, we need to always allocate a 34291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // HeapNumber. 34301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); 34311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Set the value. 34321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(eax, ecx); 34331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 34341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 34351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 34361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ SmiTag(eax); 34371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 34381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 34391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // If we fail allocation of the HeapNumber, we still have a value on 34411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // top of the FPU stack. Remove it. 34421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&failed_allocation); 34433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fstp(0); 34441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Fall through to slow case. 34451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Slow case: Jump to runtime. 34471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&slow); 3448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Counters* counters = masm->isolate()->counters(); 344944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_external_array_slow(), 1); 3450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 34511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------- S t a t e ------------- 34521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- eax : key 34531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- edx : receiver 34541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- esp[0] : return address 34551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 34561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Slow(); 3458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(ic, RelocInfo::CODE_TARGET); 34591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- eax : key 3462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- edx : receiver 3463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- esp[0] : return address 3464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 34651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Miss case: Jump to runtime. 3467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 3468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> miss_ic = 3469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 3470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(miss_ic, RelocInfo::CODE_TARGET); 34711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 34721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreExternalArray( 3475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MacroAssembler* masm, 3476589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind) { 34771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------- S t a t e ------------- 3478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- eax : key 34791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- edx : receiver 34801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- esp[0] : return address 34811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 3482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss_force_generic, slow, check_heap_number; 348344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 3485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 348644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 34871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the key is a smi. 34883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(ecx, &miss_force_generic); 34891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the index is in range. 349144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 349269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmp(ecx, FieldOperand(edi, ExternalArray::kLengthOffset)); 34931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Unsigned comparison catches both negative and too-large values. 34941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(above_equal, &slow); 34951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Handle both smis and HeapNumbers in the fast path. Go to the 34971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // runtime for all other kinds of values. 34981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // eax: value 34991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // edx: receiver 35001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ecx: key 35011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // edi: elements array 3502589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) { 35033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(eax, &slow); 35043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 35053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(eax, &check_heap_number); 35063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 350744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 35081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // smi case 350969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov(ebx, eax); // Preserve the value in eax as the return value. 351069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ SmiUntag(ebx); 35111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); 351269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // edi: base pointer of external storage 35133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3514589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 351569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ ClampUint8(ebx); 351669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ SmiUntag(ecx); 351769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov_b(Operand(edi, ecx, times_1, 0), ebx); 351844f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3519589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 3520589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 352169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ SmiUntag(ecx); 352269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov_b(Operand(edi, ecx, times_1, 0), ebx); 35231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3524589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 3525589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 352669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov_w(Operand(edi, ecx, times_1, 0), ebx); 35271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3528589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 3529589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 353069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov(Operand(edi, ecx, times_2, 0), ebx); 35311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3532589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 3533589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 35341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Need to perform int-to-float conversion. 353569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ push(ebx); 35361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ fild_s(Operand(esp, 0)); 353769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ pop(ebx); 3538589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 353969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ fstp_s(Operand(edi, ecx, times_2, 0)); 3540589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { // elements_kind == EXTERNAL_DOUBLE_ELEMENTS. 354169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ fstp_d(Operand(edi, ecx, times_4, 0)); 3542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 35431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 35441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block default: 35451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 35461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 35471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 35481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); // Return the original value. 35491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 355044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // TODO(danno): handle heap number -> pixel array conversion 3551589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) { 355244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&check_heap_number); 355344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // eax: value 355444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // edx: receiver 355544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // ecx: key 355644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // edi: elements array 355744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 3558257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Immediate(masm->isolate()->factory()->heap_number_map())); 355944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(not_equal, &slow); 356044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 356144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // The WebGL specification leaves the behavior of storing NaN and 356244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // +/-Infinity into integer arrays basically undefined. For more 356344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // reproducible behavior, convert these to zero. 356444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); 356544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // edi: base pointer of external storage 3566589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 356744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); 356869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ fstp_s(Operand(edi, ecx, times_2, 0)); 356944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ ret(0); 3570589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 3571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); 357269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ fstp_d(Operand(edi, ecx, times_4, 0)); 3573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ret(0); 357444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 357544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Perform float-to-int conversion with truncation (round-to-zero) 357644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // behavior. 357744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 357844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // For the moment we make the slow call to the runtime on 357944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // processors that don't support SSE2. The code in IntegerConvert 358044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // (code-stubs-ia32.cc) is roughly what is needed here though the 358144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // conversion failure case does not need to be handled. 35828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CpuFeatures::IsSupported(SSE2)) { 3583589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind != EXTERNAL_INT_ELEMENTS && 3584589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch elements_kind != EXTERNAL_UNSIGNED_INT_ELEMENTS) { 35858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(CpuFeatures::IsSupported(SSE2)); 35861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CpuFeatures::Scope scope(SSE2); 358769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cvttsd2si(ebx, FieldOperand(eax, HeapNumber::kValueOffset)); 358844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // ecx: untagged integer value 35893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3590589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 359169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ ClampUint8(ebx); 359269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Fall through. 3593589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 3594589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 359569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ SmiUntag(ecx); 359669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov_b(Operand(edi, ecx, times_1, 0), ebx); 359744f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3598589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 3599589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 360069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov_w(Operand(edi, ecx, times_1, 0), ebx); 360144f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 360244f0eee88ff00398ff7f715fab053374d808c90dSteve Block default: 360344f0eee88ff00398ff7f715fab053374d808c90dSteve Block UNREACHABLE(); 360444f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 360544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 360644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 36078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CpuFeatures::IsSupported(SSE3)) { 360844f0eee88ff00398ff7f715fab053374d808c90dSteve Block CpuFeatures::Scope scope(SSE3); 360944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // fisttp stores values as signed integers. To represent the 361044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // entire range of int and unsigned int arrays, store as a 361144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // 64-bit int and discard the high 32 bits. 361244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // If the value is NaN or +/-infinity, the result is 0x80000000, 361344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // which is automatically zero when taken mod 2^n, n < 32. 361444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); 36153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(esp, Immediate(2 * kPointerSize)); 361644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ fisttp_d(Operand(esp, 0)); 361769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ pop(ebx); 36183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(esp, Immediate(kPointerSize)); 361944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 36208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(CpuFeatures::IsSupported(SSE2)); 362144f0eee88ff00398ff7f715fab053374d808c90dSteve Block CpuFeatures::Scope scope(SSE2); 362244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // We can easily implement the correct rounding behavior for the 362344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // range [0, 2^31-1]. For the time being, to keep this code simple, 362444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // make the slow runtime call for values outside this range. 362544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Note: we could do better for signed int arrays. 362644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); 362744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // We will need the key if we have to make the slow runtime call. 362869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ push(ebx); 362969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ LoadPowerOf2(xmm1, ebx, 31); 363069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ pop(ebx); 363144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ ucomisd(xmm1, xmm0); 363244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(above_equal, &slow); 363369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cvttsd2si(ebx, Operand(xmm0)); 363444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 363569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // ebx: untagged integer value 363669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov(Operand(edi, ecx, times_2, 0), ebx); 36371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 363844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ ret(0); // Return original value. 36391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 36401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 36411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 36421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Slow case: call runtime. 36441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&slow); 3645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Counters* counters = masm->isolate()->counters(); 3646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->keyed_store_external_array_slow(), 1); 3647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 36481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------- S t a t e ------------- 36491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- eax : value 36501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- ecx : key 36511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- edx : receiver 36521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- esp[0] : return address 36531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 36541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow(); 3656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(ic, RelocInfo::CODE_TARGET); 3657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- eax : value 3660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ecx : key 3661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- edx : receiver 3662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- esp[0] : return address 3663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 3666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> miss_ic = 3667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 3668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(miss_ic, RelocInfo::CODE_TARGET); 3669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) { 3673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- eax : key 3675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- edx : receiver 3676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- esp[0] : return address 3677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss_force_generic; 3679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 3681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 3682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is a smi. 36843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(eax, &miss_force_generic); 3685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the elements array. 3687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); 3688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AssertFastElements(ecx); 3689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is within bounds. 3691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); 3692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above_equal, &miss_force_generic); 3693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the result and make sure it's not the hole. 3695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(ebx, Operand(ecx, eax, times_2, 3696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FixedArray::kHeaderSize - kHeapObjectTag)); 3697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(ebx, masm->isolate()->factory()->the_hole_value()); 3698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &miss_force_generic); 3699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(eax, ebx); 3700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ret(0); 3701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 3703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> miss_ic = 3704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 3705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(miss_ic, RelocInfo::CODE_TARGET); 3706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 37093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastDoubleElement( 37103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MacroAssembler* masm) { 37113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------- S t a t e ------------- 37123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- eax : key 37133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- edx : receiver 37143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- esp[0] : return address 37153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------------------------------- 37163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label miss_force_generic, slow_allocate_heapnumber; 37173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 37193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // have been verified by the caller to not be a smi. 37203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is a smi. 37223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(eax, &miss_force_generic); 37233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Get the elements array. 37253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); 37263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ AssertFastElements(ecx); 37273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is within bounds. 37293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp(eax, FieldOperand(ecx, FixedDoubleArray::kLengthOffset)); 37303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(above_equal, &miss_force_generic); 37313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check for the hole 37333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32); 37343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp(FieldOperand(ecx, eax, times_4, offset), Immediate(kHoleNanUpper32)); 37353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(equal, &miss_force_generic); 37363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Always allocate a heap number for the result. 37383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (CpuFeatures::IsSupported(SSE2)) { 37393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CpuFeatures::Scope use_sse2(SSE2); 37403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movdbl(xmm0, FieldOperand(ecx, eax, times_4, 37413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FixedDoubleArray::kHeaderSize)); 37423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 37433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ fld_d(FieldOperand(ecx, eax, times_4, FixedDoubleArray::kHeaderSize)); 37443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 37453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ AllocateHeapNumber(ecx, ebx, edi, &slow_allocate_heapnumber); 37463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Set the value. 37473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (CpuFeatures::IsSupported(SSE2)) { 37483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CpuFeatures::Scope use_sse2(SSE2); 37493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movdbl(FieldOperand(ecx, HeapNumber::kValueOffset), xmm0); 37503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 37513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ fstp_d(FieldOperand(ecx, HeapNumber::kValueOffset)); 37523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 37533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(eax, ecx); 37543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ret(0); 37553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&slow_allocate_heapnumber); 37573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // A value was pushed on the floating point stack before the allocation, if 37583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // the allocation fails it needs to be removed. 37593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!CpuFeatures::IsSupported(SSE2)) { 37603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fstp(0); 37613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 37623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> slow_ic = 37633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_Slow(); 37643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(slow_ic, RelocInfo::CODE_TARGET); 37653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&miss_force_generic); 37673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> miss_ic = 37683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 37693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(miss_ic, RelocInfo::CODE_TARGET); 37703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 37713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastElement( 37743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler* masm, 37753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_js_array, 37763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind elements_kind, 37773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch KeyedAccessGrowMode grow_mode) { 3778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 37793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- eax : value 37803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- ecx : key 3781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- edx : receiver 3782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- esp[0] : return address 3783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 37843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label miss_force_generic, grow, slow, transition_elements_kind; 37853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label check_capacity, prepare_slow, finish_store, commit_backing_store; 3786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 3788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 3789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is a smi. 37913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(ecx, &miss_force_generic); 37921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { 37943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfNotSmi(eax, &transition_elements_kind); 37953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 37963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the elements array and make sure it is a fast element array, not 'cow'. 3798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 3799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (is_js_array) { 3800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is within bounds. 3801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis. 38023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (grow_mode == ALLOW_JSARRAY_GROWTH) { 38033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &grow); 38043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 38053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &miss_force_generic); 38063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is within bounds. 3809257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis. 3810257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above_equal, &miss_force_generic); 3811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 38133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(FieldOperand(edi, HeapObject::kMapOffset), 38143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(masm->isolate()->factory()->fixed_array_map())); 38153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &miss_force_generic); 38163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&finish_store); 38183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { 38193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ecx is a smi, use times_half_pointer_size instead of 38203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // times_pointer_size 38213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(edi, 38223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ecx, 38233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch times_half_pointer_size, 38243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArray::kHeaderSize), eax); 38253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 38263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(elements_kind == FAST_ELEMENTS); 38273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Do the store and update the write barrier. 38283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ecx is a smi, use times_half_pointer_size instead of 38293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // times_pointer_size 38303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lea(ecx, FieldOperand(edi, 38313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ecx, 38323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch times_half_pointer_size, 38333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArray::kHeaderSize)); 38343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(Operand(ecx, 0), eax); 38353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure to preserve the value in register eax. 38363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ebx, eax); 38373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWrite(edi, ecx, ebx, kDontSaveFPRegs); 38383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3840257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Done. 3841257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ret(0); 38421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Handle store cache miss, replacing the ic with the generic stub. 3844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 3845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic_force_generic = 3846257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 3847257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); 38483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Handle transition to other elements kinds without using the generic stub. 38503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&transition_elements_kind); 38513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); 38523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(ic_miss, RelocInfo::CODE_TARGET); 38533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) { 38553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Handle transition requiring the array to grow. 38563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&grow); 38573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure the array is only growing by a single element, anything else 38593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // must be handled by the runtime. Flags are already set by previous 38603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // compare. 38613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &miss_force_generic); 38623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for the empty array, and preallocate a small backing store if 38643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // possible. 38653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 38663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(edi, Immediate(masm->isolate()->factory()->empty_fixed_array())); 38673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &check_capacity); 38683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int size = FixedArray::SizeFor(JSArray::kPreallocatedArrayElements); 38703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(size, edi, ebx, ecx, &prepare_slow, TAG_OBJECT); 38713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Restore the key, which is known to be the array length. 38723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // eax: value 38743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ecx: key 38753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // edx: receiver 38763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // edi: elements 38773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure that the backing store can hold additional elements. 38783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(edi, JSObject::kMapOffset), 38793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(masm->isolate()->factory()->fixed_array_map())); 38803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(edi, FixedArray::kLengthOffset), 38813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(Smi::FromInt(JSArray::kPreallocatedArrayElements))); 38823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ebx, Immediate(masm->isolate()->factory()->the_hole_value())); 38833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 1; i < JSArray::kPreallocatedArrayElements; ++i) { 38843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(edi, FixedArray::SizeFor(i)), ebx); 38853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 38863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the element at index zero. 38883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(edi, FixedArray::SizeFor(0)), eax); 38893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Install the new backing store in the JSArray. 38913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(edx, JSObject::kElementsOffset), edi); 38923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(edx, JSObject::kElementsOffset, edi, ebx, 38933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 38943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Increment the length of the array. 38963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(edx, JSArray::kLengthOffset), 38973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(Smi::FromInt(1))); 38983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ret(0); 38993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&check_capacity); 39013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(FieldOperand(edi, HeapObject::kMapOffset), 39023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(masm->isolate()->factory()->fixed_cow_array_map())); 39033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, &miss_force_generic); 39043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // eax: value 39063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ecx: key 39073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // edx: receiver 39083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // edi: elements 39093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure that the backing store can hold additional elements. 39103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); 39113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &slow); 39123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Grow the array and finish the store. 39143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(FieldOperand(edx, JSArray::kLengthOffset), 39153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(Smi::FromInt(1))); 39163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&finish_store); 39173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&prepare_slow); 39193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Restore the key, which is known to be the array length. 39203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ecx, Immediate(0)); 39213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&slow); 39233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow(); 39243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(ic_slow, RelocInfo::CODE_TARGET); 39253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 39261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 39271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 39281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 39293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( 39303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MacroAssembler* masm, 39313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_js_array, 39323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch KeyedAccessGrowMode grow_mode) { 39333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------- S t a t e ------------- 39343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- eax : value 39353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- ecx : key 39363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- edx : receiver 39373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- esp[0] : return address 39383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------------------------------- 39393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label miss_force_generic, transition_elements_kind, grow, slow; 39403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label check_capacity, prepare_slow, finish_store, commit_backing_store; 39413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 39423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 39433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // have been verified by the caller to not be a smi. 39443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 39453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is a smi. 39463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(ecx, &miss_force_generic); 39473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 39483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Get the elements array. 39493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 39503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ AssertFastElements(edi); 39513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 39523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (is_js_array) { 39533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is within bounds. 39543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis. 39553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (grow_mode == ALLOW_JSARRAY_GROWTH) { 39563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &grow); 39573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 39583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &miss_force_generic); 39593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 39603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 39613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is within bounds. 39623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis. 39633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &miss_force_generic); 396485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch } 396585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 39663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&finish_store); 39673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ StoreNumberToDoubleElements(eax, edi, ecx, edx, xmm0, 39683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &transition_elements_kind, true); 39693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ret(0); 39703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 39713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Handle store cache miss, replacing the ic with the generic stub. 39723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&miss_force_generic); 39733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> ic_force_generic = 39743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 39753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); 39763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Handle transition to other elements kinds without using the generic stub. 39783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&transition_elements_kind); 39793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); 39803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(ic_miss, RelocInfo::CODE_TARGET); 39813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) { 39833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Handle transition requiring the array to grow. 39843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&grow); 39853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure the array is only growing by a single element, anything else 39873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // must be handled by the runtime. Flags are already set by previous 39883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // compare. 39893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &miss_force_generic); 39903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Transition on values that can't be stored in a FixedDoubleArray. 39923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label value_is_smi; 39933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(eax, &value_is_smi); 39943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 39953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(Handle<Map>(masm->isolate()->heap()->heap_number_map()))); 39963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &transition_elements_kind); 39973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&value_is_smi); 39983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for the empty array, and preallocate a small backing store if 40003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // possible. 40013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 40023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(edi, Immediate(masm->isolate()->factory()->empty_fixed_array())); 40033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &check_capacity); 40043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int size = FixedDoubleArray::SizeFor(JSArray::kPreallocatedArrayElements); 40063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(size, edi, ebx, ecx, &prepare_slow, TAG_OBJECT); 40073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Restore the key, which is known to be the array length. 40083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ecx, Immediate(0)); 40093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // eax: value 40113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ecx: key 40123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // edx: receiver 40133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // edi: elements 40143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Initialize the new FixedDoubleArray. Leave elements unitialized for 40153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // efficiency, they are guaranteed to be initialized before use. 40163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(edi, JSObject::kMapOffset), 40173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(masm->isolate()->factory()->fixed_double_array_map())); 40183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(edi, FixedDoubleArray::kLengthOffset), 40193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(Smi::FromInt(JSArray::kPreallocatedArrayElements))); 40203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Install the new backing store in the JSArray. 40223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(edx, JSObject::kElementsOffset), edi); 40233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(edx, JSObject::kElementsOffset, edi, ebx, 40243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 40253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Increment the length of the array. 40273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(FieldOperand(edx, JSArray::kLengthOffset), 40283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(Smi::FromInt(1))); 40293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 40303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&finish_store); 40313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&check_capacity); 40333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // eax: value 40343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ecx: key 40353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // edx: receiver 40363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // edi: elements 40373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure that the backing store can hold additional elements. 40383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(ecx, FieldOperand(edi, FixedDoubleArray::kLengthOffset)); 40393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &slow); 40403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Grow the array and finish the store. 40423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(FieldOperand(edx, JSArray::kLengthOffset), 40433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(Smi::FromInt(1))); 40443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&finish_store); 40453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&prepare_slow); 40473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Restore the key, which is known to be the array length. 40483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ecx, Immediate(0)); 40493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&slow); 40513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow(); 40523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(ic_slow, RelocInfo::CODE_TARGET); 40533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 40543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 40553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 40563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 4058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 4060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 4061f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_IA32 4062