stub-cache-ia32.cc revision 59151504615d929945dc59db37bf1166937748c6
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2006-2009 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" 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "codegen-inl.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 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void ProbeTable(MacroAssembler* masm, 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Flags flags, 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCache::Table table, 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register name, 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register offset, 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register extra) { 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference key_offset(SCTableReference::keyReference(table)); 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference value_offset(SCTableReference::valueReference(table)); 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (extra.is_valid()) { 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the code entry from the cache. 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(extra, Operand::StaticArray(offset, times_2, value_offset)); 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the key in the entry matches the name. 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(name, Operand::StaticArray(offset, times_2, key_offset)); 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss, not_taken); 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the flags match what we're looking for. 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(offset, FieldOperand(extra, Code::kFlagsOffset)); 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(offset, ~Code::kFlagsNotUsedInLookup); 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(offset, flags); 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss); 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the first instruction in the code stub. 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(Operand(extra), Immediate(Code::kHeaderSize - kHeapObjectTag)); 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(Operand(extra)); 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save the offset on the stack. 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(offset); 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the key in the entry matches the name. 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(name, Operand::StaticArray(offset, times_2, key_offset)); 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss, not_taken); 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the code entry from the cache. 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(offset, Operand::StaticArray(offset, times_2, value_offset)); 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the flags match what we're looking for. 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(offset, FieldOperand(offset, Code::kFlagsOffset)); 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(offset, ~Code::kFlagsNotUsedInLookup); 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(offset, flags); 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss); 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore offset and re-load code entry from cache. 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(offset); 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(offset, Operand::StaticArray(offset, times_2, value_offset)); 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the first instruction in the code stub. 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(Operand(offset), Immediate(Code::kHeaderSize - kHeapObjectTag)); 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(Operand(offset)); 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pop at miss. 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(offset); 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1048defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Helper function used to check that the dictionary doesn't contain 1058defd9ff6930b4e24729971a61cf7469daf119beSteve Block// the property. This function may return false negatives, so miss_label 1068defd9ff6930b4e24729971a61cf7469daf119beSteve Block// must always call a backup property check that is complete. 1078defd9ff6930b4e24729971a61cf7469daf119beSteve Block// This function is safe to call if the receiver has fast properties. 1088defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Name must be a symbol and receiver must be a heap object. 1098defd9ff6930b4e24729971a61cf7469daf119beSteve Blockstatic void GenerateDictionaryNegativeLookup(MacroAssembler* masm, 1108defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label* miss_label, 1118defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register receiver, 1128defd9ff6930b4e24729971a61cf7469daf119beSteve Block String* name, 1138defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register r0, 1143bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register r1) { 1158defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(name->IsSymbol()); 1168defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ IncrementCounter(&Counters::negative_lookups, 1); 1178defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ IncrementCounter(&Counters::negative_lookups_miss, 1); 1188defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1198defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label done; 1208defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); 1218defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1228defd9ff6930b4e24729971a61cf7469daf119beSteve Block const int kInterceptorOrAccessCheckNeededMask = 1238defd9ff6930b4e24729971a61cf7469daf119beSteve Block (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); 1243bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1258defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Bail out if the receiver has a named interceptor or requires access checks. 1263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ test_b(FieldOperand(r0, Map::kBitFieldOffset), 1273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch kInterceptorOrAccessCheckNeededMask); 1288defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(not_zero, miss_label, not_taken); 1298defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Check that receiver is a JSObject. 1318defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ CmpInstanceType(r0, FIRST_JS_OBJECT_TYPE); 1328defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(below, miss_label, not_taken); 1338defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1348defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Load properties array. 1358defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register properties = r0; 1368defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); 1378defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1388defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Check that the properties array is a dictionary. 1398defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ cmp(FieldOperand(properties, HeapObject::kMapOffset), 1408defd9ff6930b4e24729971a61cf7469daf119beSteve Block Immediate(Factory::hash_table_map())); 1418defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(not_equal, miss_label); 1428defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1438defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Compute the capacity mask. 1448defd9ff6930b4e24729971a61cf7469daf119beSteve Block const int kCapacityOffset = 1458defd9ff6930b4e24729971a61cf7469daf119beSteve Block StringDictionary::kHeaderSize + 1468defd9ff6930b4e24729971a61cf7469daf119beSteve Block StringDictionary::kCapacityIndex * kPointerSize; 1478defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1488defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Generate an unrolled loop that performs a few probes before 1498defd9ff6930b4e24729971a61cf7469daf119beSteve Block // giving up. 1508defd9ff6930b4e24729971a61cf7469daf119beSteve Block static const int kProbes = 4; 1518defd9ff6930b4e24729971a61cf7469daf119beSteve Block const int kElementsStartOffset = 1528defd9ff6930b4e24729971a61cf7469daf119beSteve Block StringDictionary::kHeaderSize + 1538defd9ff6930b4e24729971a61cf7469daf119beSteve Block StringDictionary::kElementsStartIndex * kPointerSize; 1548defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1558defd9ff6930b4e24729971a61cf7469daf119beSteve Block // If names of slots in range from 1 to kProbes - 1 for the hash value are 1568defd9ff6930b4e24729971a61cf7469daf119beSteve Block // not equal to the name and kProbes-th slot is not used (its name is the 1578defd9ff6930b4e24729971a61cf7469daf119beSteve Block // undefined value), it guarantees the hash table doesn't contain the 1588defd9ff6930b4e24729971a61cf7469daf119beSteve Block // property. It's true even if some slots represent deleted properties 1598defd9ff6930b4e24729971a61cf7469daf119beSteve Block // (their names are the null value). 1608defd9ff6930b4e24729971a61cf7469daf119beSteve Block for (int i = 0; i < kProbes; i++) { 1618defd9ff6930b4e24729971a61cf7469daf119beSteve Block // r0 points to properties hash. 1628defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Compute the masked index: (hash + i + i * i) & mask. 1633bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register index = r1; 1648defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Capacity is smi 2^n. 1658defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(index, FieldOperand(properties, kCapacityOffset)); 1668defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ dec(index); 1678defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ and_(Operand(index), 1688defd9ff6930b4e24729971a61cf7469daf119beSteve Block Immediate(Smi::FromInt(name->Hash() + 1698defd9ff6930b4e24729971a61cf7469daf119beSteve Block StringDictionary::GetProbeOffset(i)))); 1708defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1718defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Scale the index by multiplying by the entry size. 1728defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(StringDictionary::kEntrySize == 3); 1738defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ lea(index, Operand(index, index, times_2, 0)); // index *= 3. 1748defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1753bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register entity_name = r1; 1768defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Having undefined at this place means the name is not contained. 1778defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT_EQ(kSmiTagSize, 1); 1788defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(entity_name, Operand(properties, index, times_half_pointer_size, 1798defd9ff6930b4e24729971a61cf7469daf119beSteve Block kElementsStartOffset - kHeapObjectTag)); 1808defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ cmp(entity_name, Factory::undefined_value()); 1818defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (i != kProbes - 1) { 1828defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(equal, &done, taken); 1838defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1848defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Stop if found the property. 1858defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ cmp(entity_name, Handle<String>(name)); 1868defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(equal, miss_label, not_taken); 1878defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1883bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Check if the entry name is not a symbol. 1893bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ mov(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset)); 1903bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ test_b(FieldOperand(entity_name, Map::kInstanceTypeOffset), 1913bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch kIsSymbolMask); 1923bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ j(zero, miss_label, not_taken); 1938defd9ff6930b4e24729971a61cf7469daf119beSteve Block } else { 1948defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Give up probing if still not found the undefined value. 1958defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(not_equal, miss_label, not_taken); 1968defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 1978defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 1988defd9ff6930b4e24729971a61cf7469daf119beSteve Block 1998defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ bind(&done); 2008defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ DecrementCounter(&Counters::negative_lookups_miss, 1); 2018defd9ff6930b4e24729971a61cf7469daf119beSteve Block} 2028defd9ff6930b4e24729971a61cf7469daf119beSteve Block 2038defd9ff6930b4e24729971a61cf7469daf119beSteve Block 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCache::GenerateProbe(MacroAssembler* masm, 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Flags flags, 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register name, 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register extra) { 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure that code is valid. The shifting code relies on the 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // entry size being 8. 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(sizeof(Entry) == 8); 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure the flags does not name a specific type. 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(Code::ExtractTypeFromFlags(flags) == 0); 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure that there are no register conflicts. 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!scratch.is(receiver)); 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!scratch.is(name)); 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!extra.is(receiver)); 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!extra.is(name)); 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!extra.is(scratch)); 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(receiver, Immediate(kSmiTagMask)); 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &miss, not_taken); 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the map of the receiver and compute the hash. 231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ xor_(scratch, flags); 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the primary table. 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ProbeTable(masm, flags, kPrimary, name, scratch, extra); 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Primary miss: Compute hash for secondary probe. 240d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ xor_(scratch, flags); 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(scratch, Operand(name)); 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(Operand(scratch), Immediate(flags)); 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(scratch, (kSecondaryTableSize - 1) << kHeapObjectTagSize); 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the secondary table. 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ProbeTable(masm, flags, kSecondary, name, scratch, extra); 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cache miss: Fall-through and let caller handle the miss by 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // entering the runtime system. 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index, 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register prototype) { 26080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadGlobalFunction(index, prototype); 26180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadGlobalFunctionInitialMap(prototype, prototype); 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the prototype from the initial map. 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( 2687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch MacroAssembler* masm, int index, Register prototype) { 2697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Get the global function with the given index. 2707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch JSFunction* function = JSFunction::cast(Top::global_context()->get(index)); 2717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Load its initial map. The global functions all have initial maps. 2727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Set(prototype, Immediate(Handle<Map>(function->initial_map()))); 2737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Load the prototype from the initial map. 2747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); 2757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 2767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss_label) { 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(receiver, Immediate(kSmiTagMask)); 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, miss_label, not_taken); 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is a JS array. 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, miss_label, not_taken); 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load length directly from the JS array. 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset)); 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate code to check if an object is a string. If the object is 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// a string, the map's instance type is left in the scratch register. 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GenerateStringCheck(MacroAssembler* masm, 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* smi, 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* non_string_object) { 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object isn't a smi. 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(receiver, Immediate(kSmiTagMask)); 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, smi, not_taken); 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is a string. 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(kNotStringTag != 0); 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(scratch, Immediate(kNotStringTag)); 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, non_string_object, not_taken); 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 318402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register scratch1, 319402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register scratch2, 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 321402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label check_wrapper; 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the object is a string leaving the instance type in the 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch register. 325402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateStringCheck(masm, receiver, scratch1, miss, &check_wrapper); 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 327d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Load length from the string and convert to a smi. 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, FieldOperand(receiver, String::kLengthOffset)); 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the object is a JSValue wrapper. 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&check_wrapper); 333402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(scratch1, JS_VALUE_TYPE); 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, miss, not_taken); 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the wrapped value is a string and load the length 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // directly if it is. 338402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset)); 339402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateStringCheck(masm, scratch2, scratch1, miss, miss); 340402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, FieldOperand(scratch2, String::kLengthOffset)); 341402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ret(0); 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss_label) { 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, Operand(scratch1)); 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Load a fast property out of a holder object (src). In-object properties 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// are loaded directly otherwise the property is loaded from the properties 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// fixed array. 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register dst, Register src, 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, int index) { 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust for the number of properties stored in the holder. 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block index -= holder->map()->inobject_properties(); 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (index < 0) { 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the property straight out of the holder. 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = holder->map()->instance_size() + (index * kPointerSize); 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(dst, FieldOperand(src, offset)); 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the offset into the properties array. 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = index * kPointerSize + FixedArray::kHeaderSize; 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(dst, FieldOperand(dst, offset)); 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 377402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescustatic void PushInterceptorArguments(MacroAssembler* masm, 378402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register receiver, 379402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register holder, 380402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register name, 381402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu JSObject* holder_obj) { 382402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(name); 383402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); 384402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(!Heap::InNewSpace(interceptor)); 3856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch = name; 3866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(scratch, Immediate(Handle<Object>(interceptor))); 3876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(scratch); 388402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(receiver); 3896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(holder); 3906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(FieldOperand(scratch, InterceptorInfo::kDataOffset)); 391402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 392402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 393402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register holder, 397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register name, 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder_obj) { 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PushInterceptorArguments(masm, receiver, holder, name, holder_obj); 400402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CallExternalReference( 401402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly)), 402402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 5); 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 406402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// Reserves space for the extra arguments to FastHandleApiCall in the 407402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// caller's frame. 408402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// 409402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// These arguments are set by CheckPrototypes and GenerateFastApiCall. 410402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescustatic void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { 411402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------- S t a t e ------------- 412402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- esp[0] : return address 413402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- esp[4] : last argument in the internal frame of the caller 414402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------------------------------- 415402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(scratch); 416402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(Immediate(Smi::FromInt(0))); 417402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(Immediate(Smi::FromInt(0))); 418402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(Immediate(Smi::FromInt(0))); 419402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(Immediate(Smi::FromInt(0))); 420402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(scratch); 421402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 422402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 423402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 424402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// Undoes the effects of ReserveSpaceForFastApiCall. 425402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescustatic void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { 426402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------- S t a t e ------------- 427402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- esp[0] : return address 428402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- esp[4] : last fast api call extra argument 429402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- ... 430402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- esp[16] : first fast api call extra argument 431402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- esp[20] : last argument in the internal frame 432402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------------------------------- 433402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(scratch); 434402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ add(Operand(esp), Immediate(kPointerSize * 4)); 435402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(scratch); 436402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 437402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 438402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 439402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// Generates call to FastHandleApiCall builtin. 440402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescustatic void GenerateFastApiCall(MacroAssembler* masm, 441402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu const CallOptimization& optimization, 442402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int argc) { 443402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------- S t a t e ------------- 444402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- esp[0] : return address 445402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- esp[4] : object passing the type check 446402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // (last fast api call extra argument, 447402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // set by CheckPrototypes) 448402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- esp[8] : api call data 449402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- esp[12] : api callback 450402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- esp[16] : api function 451402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // (first fast api call extra argument) 452402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- esp[20] : last argument 453402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- ... 454402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- esp[(argc + 5) * 4] : first argument 455402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- esp[(argc + 6) * 4] : receiver 456402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ----------------------------------- 457402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 458402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Get the function and setup the context. 459402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu JSFunction* function = optimization.constant_function(); 460402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(edi, Immediate(Handle<JSFunction>(function))); 461402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 462402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 463402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Pass the additional arguments FastHandleApiCall expects. 464402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(Operand(esp, 4 * kPointerSize), edi); 465402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu bool info_loaded = false; 466402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Object* callback = optimization.api_call_info()->callback(); 467402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (Heap::InNewSpace(callback)) { 468402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu info_loaded = true; 469402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, Handle<CallHandlerInfo>(optimization.api_call_info())); 470402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kCallbackOffset)); 471402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(Operand(esp, 3 * kPointerSize), ebx); 472402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 473402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(Operand(esp, 3 * kPointerSize), Immediate(Handle<Object>(callback))); 474402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 475402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Object* call_data = optimization.api_call_info()->data(); 476402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (Heap::InNewSpace(call_data)) { 477402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (!info_loaded) { 478402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ecx, Handle<CallHandlerInfo>(optimization.api_call_info())); 479402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 480402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset)); 481402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(Operand(esp, 2 * kPointerSize), ebx); 482402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 483402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(Operand(esp, 2 * kPointerSize), 484402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Immediate(Handle<Object>(call_data))); 485402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 486402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 487402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Set the number of arguments. 488402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, Immediate(argc + 4)); 489402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 490402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Jump to the fast api call builtin (tail call). 491402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Handle<Code> code = Handle<Code>( 492402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Builtins::builtin(Builtins::FastHandleApiCall)); 493402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ParameterCount expected(0); 494402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ InvokeCode(code, expected, expected, 495402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu RelocInfo::CODE_TARGET, JUMP_FUNCTION); 496402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 497402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 498402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CallInterceptorCompiler BASE_EMBEDDED { 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 501402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu CallInterceptorCompiler(StubCompiler* stub_compiler, 502402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu const ParameterCount& arguments, 503402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register name) 504402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu : stub_compiler_(stub_compiler), 505402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu arguments_(arguments), 506402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu name_(name) {} 507402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 508402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void Compile(MacroAssembler* masm, 509402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu JSObject* object, 510402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu JSObject* holder, 511402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu String* name, 512402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu LookupResult* lookup, 513402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register receiver, 514402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register scratch1, 515402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register scratch2, 5163bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 517402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label* miss) { 518402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(holder->HasNamedInterceptor()); 519402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); 520402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 521402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Check that the receiver isn't a smi. 522402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ test(receiver, Immediate(kSmiTagMask)); 523402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ j(zero, miss, not_taken); 524402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 525402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu CallOptimization optimization(lookup); 526402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 5276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (optimization.is_constant_call()) { 528402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu CompileCacheable(masm, 529402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu object, 530402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu receiver, 531402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu scratch1, 532402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu scratch2, 5333bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch3, 534402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu holder, 535402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu lookup, 536402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu name, 537402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu optimization, 538402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu miss); 539402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 540402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu CompileRegular(masm, 541402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu object, 542402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu receiver, 543402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu scratch1, 544402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu scratch2, 5453bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch3, 546402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu name, 547402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu holder, 548402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu miss); 549402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 550402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 552402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu private: 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CompileCacheable(MacroAssembler* masm, 554402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu JSObject* object, 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 5583bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 559f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke JSObject* interceptor_holder, 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupResult* lookup, 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name, 562402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu const CallOptimization& optimization, 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss_label) { 564402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(optimization.is_constant_call()); 565402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(!lookup->holder()->IsGlobalObject()); 566402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 567402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int depth1 = kInvalidProtoDepth; 568402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int depth2 = kInvalidProtoDepth; 569402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu bool can_do_fast_api_call = false; 570402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (optimization.is_simple_api_call() && 571402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu !lookup->holder()->IsGlobalObject()) { 572f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke depth1 = 573f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke optimization.GetPrototypeDepthOfExpectedType(object, 574f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke interceptor_holder); 575402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (depth1 == kInvalidProtoDepth) { 576f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke depth2 = 577f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke optimization.GetPrototypeDepthOfExpectedType(interceptor_holder, 578f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke lookup->holder()); 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 580402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu can_do_fast_api_call = (depth1 != kInvalidProtoDepth) || 581402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu (depth2 != kInvalidProtoDepth); 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 584402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ IncrementCounter(&Counters::call_const_interceptor, 1); 585402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 586402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (can_do_fast_api_call) { 587402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ IncrementCounter(&Counters::call_const_interceptor_fast_api, 1); 588402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ReserveSpaceForFastApiCall(masm, scratch1); 589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check that the maps from receiver to interceptor's holder 592f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // haven't changed and thus we can invoke interceptor. 593402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label miss_cleanup; 594402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; 595402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register holder = 5967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch stub_compiler_->CheckPrototypes(object, receiver, 5977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch interceptor_holder, scratch1, 5983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch2, scratch3, name, depth1, miss); 599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 600f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invoke an interceptor and if it provides a value, 601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // branch to |regular_invoke|. 602402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label regular_invoke; 603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke LoadWithInterceptor(masm, receiver, holder, interceptor_holder, 604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ®ular_invoke); 605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Interceptor returned nothing for this property. Try to use cached 607f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // constant function. 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 609f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check that the maps from interceptor's holder to constant function's 610f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // holder haven't changed and thus we can use cached constant function. 6117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (interceptor_holder != lookup->holder()) { 6127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch stub_compiler_->CheckPrototypes(interceptor_holder, receiver, 6137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch lookup->holder(), scratch1, 6143bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch2, scratch3, name, depth2, miss); 6157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 6167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // CheckPrototypes has a side effect of fetching a 'holder' 6177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // for API (object which is instanceof for the signature). It's 6187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // safe to omit it here, as if present, it should be fetched 6197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // by the previous CheckPrototypes. 6207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(depth2 == kInvalidProtoDepth); 6217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 623f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invoke function. 624402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (can_do_fast_api_call) { 625402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateFastApiCall(masm, optimization, arguments_.immediate()); 626402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 627402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ InvokeFunction(optimization.constant_function(), arguments_, 628402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu JUMP_FUNCTION); 629402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 631f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Deferred code for fast API call case---clean preallocated space. 632402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (can_do_fast_api_call) { 633402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ bind(&miss_cleanup); 634402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu FreeSpaceForFastApiCall(masm, scratch1); 635402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ jmp(miss_label); 636402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 638f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invoke a regular function. 639402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ bind(®ular_invoke); 640402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (can_do_fast_api_call) { 641402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu FreeSpaceForFastApiCall(masm, scratch1); 642402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CompileRegular(MacroAssembler* masm, 646402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu JSObject* object, 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 648402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register scratch1, 649402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register scratch2, 6503bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 651402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu String* name, 652f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke JSObject* interceptor_holder, 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss_label) { 654402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register holder = 655f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, 6563bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch1, scratch2, scratch3, name, 657402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu miss_label); 658402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ EnterInternalFrame(); 660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save the name_ register across the call. 661e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(name_); 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PushInterceptorArguments(masm, 664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block receiver, 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block holder, 666e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke name_, 667f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke interceptor_holder); 668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 669402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CallExternalReference( 670402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ExternalReference( 671402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu IC_Utility(IC::kLoadPropertyWithInterceptorForCall)), 672402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 5); 673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 674e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Restore the name_ register. 675e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ pop(name_); 676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LeaveInternalFrame(); 677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 679402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void LoadWithInterceptor(MacroAssembler* masm, 680402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register receiver, 681402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register holder, 682402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu JSObject* holder_obj, 683402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label* interceptor_succeeded) { 684402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ EnterInternalFrame(); 685402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(holder); // Save the holder. 686402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(name_); // Save the name. 687402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 688402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu CompileCallLoadPropertyWithInterceptor(masm, 689402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu receiver, 690402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu holder, 691402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu name_, 692402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu holder_obj); 693402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 694402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(name_); // Restore the name. 695402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(receiver); // Restore the holder. 696402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ LeaveInternalFrame(); 697402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 698402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(eax, Factory::no_interceptor_result_sentinel()); 699402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ j(not_equal, interceptor_succeeded); 700402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 701402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 702402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu StubCompiler* stub_compiler_; 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& arguments_; 704e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Register name_; 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { 709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); 710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code* code = NULL; 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (kind == Code::LOAD_IC) { 712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block code = Builtins::builtin(Builtins::LoadIC_Miss); 713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block code = Builtins::builtin(Builtins::KeyedLoadIC_Miss); 715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> ic(code); 718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(ic, RelocInfo::CODE_TARGET); 719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 722402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// Both name_reg and receiver_reg are preserved on jumps to miss_label, 723402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// but may be destroyed if store is successful. 724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateStoreField(MacroAssembler* masm, 725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* object, 726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index, 727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Map* transition, 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver_reg, 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register name_reg, 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss_label) { 732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object isn't a smi. 733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(receiver_reg, Immediate(kSmiTagMask)); 734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, miss_label, not_taken); 735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the object hasn't changed. 737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset), 738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(Handle<Map>(object->map()))); 739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, miss_label, not_taken); 740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform global security token check if needed. 742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsJSGlobalProxy()) { 743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); 744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stub never generated for non-global objects that require access 747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks. 748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform map transition for the receiver if necessary. 751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) { 752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The properties must be extended before we can store the value. 753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We jump to a runtime call that extends the properties array. 754402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(scratch); // Return address. 755402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(receiver_reg); 756402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(Immediate(Handle<Map>(transition))); 757402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(eax); 758402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(scratch); 7596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference( 760402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage)), 3, 1); 761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (transition != NULL) { 765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update the map of the object; no write barrier updating is 766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // needed because the map is never in new space. 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset), 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(Handle<Map>(transition))); 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust for the number of properties stored in the object. Even in the 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // face of a transition we can use the old map here because the size of the 773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object and the number of in-object properties is not going to change. 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block index -= object->map()->inobject_properties(); 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (index < 0) { 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the property straight into the object. 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = object->map()->instance_size() + (index * kPointerSize); 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(FieldOperand(receiver_reg, offset), eax); 780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update the write barrier for the array address. 782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pass the value being stored in the now unused name_reg. 783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(name_reg, Operand(eax)); 784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ RecordWrite(receiver_reg, offset, name_reg, scratch); 785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Write to the properties array. 787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = index * kPointerSize + FixedArray::kHeaderSize; 788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the properties array (optimistically). 789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); 790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(FieldOperand(scratch, offset), eax); 791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update the write barrier for the array address. 793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pass the value being stored in the now unused name_reg. 794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(name_reg, Operand(eax)); 795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ RecordWrite(scratch, offset, name_reg, receiver_reg); 796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the value (register eax). 799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Generate code to check that a global property cell is empty. Create 8046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// the property cell at compilation time if no cell exists for the 8056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// property. 8066ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic Object* GenerateCheckPropertyCell(MacroAssembler* masm, 8076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GlobalObject* global, 8086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block String* name, 8096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch, 8106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* miss) { 8116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Object* probe = global->EnsurePropertyCell(name); 8126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (probe->IsFailure()) return probe; 8136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); 8146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(cell->value()->IsTheHole()); 8156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(scratch, Immediate(Handle<Object>(cell))); 8166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), 8176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Immediate(Factory::the_hole_value())); 8186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_equal, miss, not_taken); 8196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return cell; 8206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 8216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8238defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Calls GenerateCheckPropertyCell for each global object in the prototype chain 8248defd9ff6930b4e24729971a61cf7469daf119beSteve Block// from object to (but not including) holder. 8258defd9ff6930b4e24729971a61cf7469daf119beSteve Blockstatic Object* GenerateCheckPropertyCells(MacroAssembler* masm, 8268defd9ff6930b4e24729971a61cf7469daf119beSteve Block JSObject* object, 8278defd9ff6930b4e24729971a61cf7469daf119beSteve Block JSObject* holder, 8288defd9ff6930b4e24729971a61cf7469daf119beSteve Block String* name, 8298defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register scratch, 8308defd9ff6930b4e24729971a61cf7469daf119beSteve Block Label* miss) { 8318defd9ff6930b4e24729971a61cf7469daf119beSteve Block JSObject* current = object; 8328defd9ff6930b4e24729971a61cf7469daf119beSteve Block while (current != holder) { 8338defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (current->IsGlobalObject()) { 8348defd9ff6930b4e24729971a61cf7469daf119beSteve Block Object* cell = GenerateCheckPropertyCell(masm, 8358defd9ff6930b4e24729971a61cf7469daf119beSteve Block GlobalObject::cast(current), 8368defd9ff6930b4e24729971a61cf7469daf119beSteve Block name, 8378defd9ff6930b4e24729971a61cf7469daf119beSteve Block scratch, 8388defd9ff6930b4e24729971a61cf7469daf119beSteve Block miss); 8398defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (cell->IsFailure()) { 8408defd9ff6930b4e24729971a61cf7469daf119beSteve Block return cell; 8418defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 8428defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 8438defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(current->IsJSObject()); 8448defd9ff6930b4e24729971a61cf7469daf119beSteve Block current = JSObject::cast(current->GetPrototype()); 8458defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 8468defd9ff6930b4e24729971a61cf7469daf119beSteve Block return NULL; 8478defd9ff6930b4e24729971a61cf7469daf119beSteve Block} 8488defd9ff6930b4e24729971a61cf7469daf119beSteve Block 8498defd9ff6930b4e24729971a61cf7469daf119beSteve Block 850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm()) 852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister StubCompiler::CheckPrototypes(JSObject* object, 855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register object_reg, 856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register holder_reg, 8583bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch1, 8593bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch2, 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name, 8618defd9ff6930b4e24729971a61cf7469daf119beSteve Block int save_at_depth, 8623bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* miss) { 8638defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Make sure there's no overlap between holder and object registers. 8643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 8653bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) 8663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch && !scratch2.is(scratch1)); 8678defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Keep track of the current object in register reg. 8688defd9ff6930b4e24729971a61cf7469daf119beSteve Block Register reg = object_reg; 8698defd9ff6930b4e24729971a61cf7469daf119beSteve Block JSObject* current = object; 8708defd9ff6930b4e24729971a61cf7469daf119beSteve Block int depth = 0; 8718defd9ff6930b4e24729971a61cf7469daf119beSteve Block 8728defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (save_at_depth == depth) { 8738defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(Operand(esp, kPointerSize), reg); 8748defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8768defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Traverse the prototype chain and check the maps in the prototype chain for 8778defd9ff6930b4e24729971a61cf7469daf119beSteve Block // fast and global objects or do negative lookup for normal objects. 8788defd9ff6930b4e24729971a61cf7469daf119beSteve Block while (current != holder) { 8798defd9ff6930b4e24729971a61cf7469daf119beSteve Block depth++; 8808defd9ff6930b4e24729971a61cf7469daf119beSteve Block 8818defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Only global objects and objects that do not require access 8828defd9ff6930b4e24729971a61cf7469daf119beSteve Block // checks are allowed in stubs. 8838defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); 8848defd9ff6930b4e24729971a61cf7469daf119beSteve Block 8858defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(current->GetPrototype()->IsJSObject()); 8868defd9ff6930b4e24729971a61cf7469daf119beSteve Block JSObject* prototype = JSObject::cast(current->GetPrototype()); 8878defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (!current->HasFastProperties() && 8888defd9ff6930b4e24729971a61cf7469daf119beSteve Block !current->IsJSGlobalObject() && 8898defd9ff6930b4e24729971a61cf7469daf119beSteve Block !current->IsJSGlobalProxy()) { 8908defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (!name->IsSymbol()) { 8918defd9ff6930b4e24729971a61cf7469daf119beSteve Block Object* lookup_result = Heap::LookupSymbol(name); 8928defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (lookup_result->IsFailure()) { 8938defd9ff6930b4e24729971a61cf7469daf119beSteve Block set_failure(Failure::cast(lookup_result)); 8948defd9ff6930b4e24729971a61cf7469daf119beSteve Block return reg; 8958defd9ff6930b4e24729971a61cf7469daf119beSteve Block } else { 8968defd9ff6930b4e24729971a61cf7469daf119beSteve Block name = String::cast(lookup_result); 8978defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 8988defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 8998defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(current->property_dictionary()->FindEntry(name) == 9008defd9ff6930b4e24729971a61cf7469daf119beSteve Block StringDictionary::kNotFound); 9018defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9028defd9ff6930b4e24729971a61cf7469daf119beSteve Block GenerateDictionaryNegativeLookup(masm(), 9038defd9ff6930b4e24729971a61cf7469daf119beSteve Block miss, 9048defd9ff6930b4e24729971a61cf7469daf119beSteve Block reg, 9058defd9ff6930b4e24729971a61cf7469daf119beSteve Block name, 9063bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch1, 9073bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch2); 9083bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); 9098defd9ff6930b4e24729971a61cf7469daf119beSteve Block reg = holder_reg; // from now the object is in holder_reg 9103bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); 9118defd9ff6930b4e24729971a61cf7469daf119beSteve Block } else if (Heap::InNewSpace(prototype)) { 9128defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Get the map of the current object. 9133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); 9143bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ cmp(Operand(scratch1), Immediate(Handle<Map>(current->map()))); 9158defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Branch on the result of the map check. 9168defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(not_equal, miss, not_taken); 9178defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Check access rights to the global object. This has to happen 9188defd9ff6930b4e24729971a61cf7469daf119beSteve Block // after the map check so that we know that the object is 9198defd9ff6930b4e24729971a61cf7469daf119beSteve Block // actually a global object. 9208defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (current->IsJSGlobalProxy()) { 9213bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ CheckAccessGlobalProxy(reg, scratch1, miss); 9228defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9238defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Restore scratch register to be the map of the object. 9248defd9ff6930b4e24729971a61cf7469daf119beSteve Block // We load the prototype from the map in the scratch register. 9253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); 9268defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 9278defd9ff6930b4e24729971a61cf7469daf119beSteve Block // The prototype is in new space; we cannot store a reference 9288defd9ff6930b4e24729971a61cf7469daf119beSteve Block // to it in the code. Load it from the map. 9298defd9ff6930b4e24729971a61cf7469daf119beSteve Block reg = holder_reg; // from now the object is in holder_reg 9303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); 9318defd9ff6930b4e24729971a61cf7469daf119beSteve Block } else { 9328defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Check the map of the current object. 9338defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ cmp(FieldOperand(reg, HeapObject::kMapOffset), 9348defd9ff6930b4e24729971a61cf7469daf119beSteve Block Immediate(Handle<Map>(current->map()))); 9358defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Branch on the result of the map check. 9368defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(not_equal, miss, not_taken); 9378defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Check access rights to the global object. This has to happen 9388defd9ff6930b4e24729971a61cf7469daf119beSteve Block // after the map check so that we know that the object is 9398defd9ff6930b4e24729971a61cf7469daf119beSteve Block // actually a global object. 9408defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (current->IsJSGlobalProxy()) { 9413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ CheckAccessGlobalProxy(reg, scratch1, miss); 942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 9438defd9ff6930b4e24729971a61cf7469daf119beSteve Block // The prototype is in old space; load it directly. 9448defd9ff6930b4e24729971a61cf7469daf119beSteve Block reg = holder_reg; // from now the object is in holder_reg 9458defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(reg, Handle<JSObject>(prototype)); 946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 9478defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9488defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (save_at_depth == depth) { 9498defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ mov(Operand(esp, kPointerSize), reg); 9508defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 9518defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9528defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Go to the next object in the prototype chain. 9538defd9ff6930b4e24729971a61cf7469daf119beSteve Block current = prototype; 954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 9558defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(current == holder); 9568defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9578defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Log the check depth. 9588defd9ff6930b4e24729971a61cf7469daf119beSteve Block LOG(IntEvent("check-maps-depth", depth + 1)); 9598defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9608defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Check the holder map. 9618defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ cmp(FieldOperand(reg, HeapObject::kMapOffset), 9628defd9ff6930b4e24729971a61cf7469daf119beSteve Block Immediate(Handle<Map>(holder->map()))); 9638defd9ff6930b4e24729971a61cf7469daf119beSteve Block __ j(not_equal, miss, not_taken); 9648defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9658defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Perform security check for access to the global object. 9668defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); 9678defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (holder->IsJSGlobalProxy()) { 9683bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ CheckAccessGlobalProxy(reg, scratch1, miss); 9698defd9ff6930b4e24729971a61cf7469daf119beSteve Block }; 9708defd9ff6930b4e24729971a61cf7469daf119beSteve Block 9718defd9ff6930b4e24729971a61cf7469daf119beSteve Block // If we've skipped any global objects, it's not enough to verify 9728defd9ff6930b4e24729971a61cf7469daf119beSteve Block // that their maps haven't changed. We also need to check that the 9738defd9ff6930b4e24729971a61cf7469daf119beSteve Block // property cell for the property is still empty. 9748defd9ff6930b4e24729971a61cf7469daf119beSteve Block Object* result = GenerateCheckPropertyCells(masm(), 9758defd9ff6930b4e24729971a61cf7469daf119beSteve Block object, 9768defd9ff6930b4e24729971a61cf7469daf119beSteve Block holder, 9778defd9ff6930b4e24729971a61cf7469daf119beSteve Block name, 9783bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch1, 9798defd9ff6930b4e24729971a61cf7469daf119beSteve Block miss); 9808defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (result->IsFailure()) set_failure(Failure::cast(result)); 981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 982402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Return the register containing the holder. 9838defd9ff6930b4e24729971a61cf7469daf119beSteve Block return reg; 984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadField(JSObject* object, 988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 9923bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index, 994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name, 995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(receiver, Immediate(kSmiTagMask)); 998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, miss, not_taken); 999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check the prototype chain. 1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register reg = 1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPrototypes(object, receiver, holder, 10033bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch1, scratch2, scratch3, name, miss); 1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the value from the properties. 1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateFastPropertyLoad(masm(), eax, reg, holder, index); 1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1011e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkebool StubCompiler::GenerateLoadCallback(JSObject* object, 1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register name_reg, 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 10173bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AccessorInfo* callback, 1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name, 1020e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* miss, 1021e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Failure** failure) { 1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(receiver, Immediate(kSmiTagMask)); 1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, miss, not_taken); 1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register reg = 1028bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch CheckPrototypes(object, receiver, holder, scratch1, 1029bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch scratch2, scratch3, name, miss); 1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1031d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Handle<AccessorInfo> callback_handle(callback); 1032d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1033d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ EnterInternalFrame(); 1034bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ PushHandleScope(scratch2); 1035bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Push the stack address where the list of arguments ends. 1036bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ mov(scratch2, esp); 1037bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ sub(Operand(scratch2), Immediate(2 * kPointerSize)); 1038bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ push(scratch2); 1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(receiver); // receiver 1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(reg); // holder 10419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Push data from AccessorInfo. 10429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (Heap::InNewSpace(callback_handle->data())) { 1043bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ mov(scratch2, Immediate(callback_handle)); 1044bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ push(FieldOperand(scratch2, AccessorInfo::kDataOffset)); 10459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } else { 10469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ push(Immediate(Handle<Object>(callback_handle->data()))); 10479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(name_reg); // name 1049d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Save a pointer to where we pushed the arguments pointer. 10506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // This will be passed as the const AccessorInfo& to the C++ callback. 1051d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(eax, esp); 10526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ add(Operand(eax), Immediate(4 * kPointerSize)); 1053d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(ebx, esp); 1054d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1055d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Do call through the api. 10566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT_EQ(5, ApiGetterEntryStub::kStackSpace); 1057d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Address getter_address = v8::ToCData<Address>(callback->getter()); 1058d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ApiFunction fun(getter_address); 1059d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ApiGetterEntryStub stub(callback_handle, &fun); 1060e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emitting a stub call may try to allocate (if the code is not 1061e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // already generated). Do not allow the assembler to perform a 1062e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // garbage collection but instead return the allocation failure 1063e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // object. 1064e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Object* result = masm()->TryCallStub(&stub); 1065e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result->IsFailure()) { 1066e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke *failure = Failure::cast(result); 1067e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return false; 1068e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1070d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // We need to avoid using eax since that now holds the result. 1071bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Register tmp = scratch2.is(eax) ? reg : scratch2; 1072e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emitting PopHandleScope may try to allocate. Do not allow the 1073e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // assembler to perform a garbage collection but instead return a 1074e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // failure object. 1075e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke result = masm()->TryPopHandleScope(eax, tmp); 1076e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result->IsFailure()) { 1077e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke *failure = Failure::cast(result); 1078e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return false; 1079e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1080d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ LeaveInternalFrame(); 1081d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1082d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ret(0); 1083e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return true; 1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadConstant(JSObject* object, 1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 10923bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* value, 1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name, 1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(receiver, Immediate(kSmiTagMask)); 1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, miss, not_taken); 1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register reg = 1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPrototypes(object, receiver, holder, 11033bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch1, scratch2, scratch3, name, miss); 1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the constant value. 1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, Handle<Object>(value)); 1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadInterceptor(JSObject* object, 11127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch JSObject* interceptor_holder, 1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupResult* lookup, 1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register name_reg, 1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 11183bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name, 1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 11217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(interceptor_holder->HasNamedInterceptor()); 11227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); 11237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the receiver isn't a smi. 11257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ test(receiver, Immediate(kSmiTagMask)); 11267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(zero, miss, not_taken); 11277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // So far the most popular follow ups for interceptor loads are FIELD 11297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // and CALLBACKS, so inline only them, other cases may be added 11307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // later. 11317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch bool compile_followup_inline = false; 11327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (lookup->IsProperty() && lookup->IsCacheable()) { 11337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (lookup->type() == FIELD) { 11347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch compile_followup_inline = true; 11357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else if (lookup->type() == CALLBACKS && 11367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch lookup->GetCallbackObject()->IsAccessorInfo() && 11377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL) { 11387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch compile_followup_inline = true; 11397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 11407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 11417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (compile_followup_inline) { 11437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Compile the interceptor call, followed by inline code to load the 11447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // property from further up the prototype chain if the call fails. 11457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps haven't changed. 11467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, 11473bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch1, scratch2, scratch3, 11483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch name, miss); 11497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1)); 11507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Save necessary data before invoking an interceptor. 11527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Requires a frame to make GC aware of pushed pointers. 11537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ EnterInternalFrame(); 11547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { 11567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // CALLBACKS case needs a receiver to be passed into C++ callback. 11577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(receiver); 11587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 11597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(holder_reg); 11607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(name_reg); 11617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Invoke an interceptor. Note: map checks from receiver to 11637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // interceptor's holder has been compiled before (see a caller 11647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // of this method.) 11657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch CompileCallLoadPropertyWithInterceptor(masm(), 11667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch receiver, 11677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch holder_reg, 11687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch name_reg, 11697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch interceptor_holder); 11707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check if interceptor provided a value for property. If it's 11727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // the case, return immediately. 11737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label interceptor_failed; 11747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ cmp(eax, Factory::no_interceptor_result_sentinel()); 11757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(equal, &interceptor_failed); 11767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LeaveInternalFrame(); 11777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ ret(0); 11787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&interceptor_failed); 11807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(name_reg); 11817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(holder_reg); 11827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { 11837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(receiver); 11847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 11857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LeaveInternalFrame(); 11877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps from interceptor's holder to lookup's holder 11897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // haven't changed. And load lookup's holder into holder_reg. 11907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (interceptor_holder != lookup->holder()) { 11917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch holder_reg = CheckPrototypes(interceptor_holder, 11927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch holder_reg, 11937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch lookup->holder(), 11947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch1, 11957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch2, 11963bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch3, 11977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch name, 11987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch miss); 11997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 12007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (lookup->type() == FIELD) { 12027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // We found FIELD property in prototype chain of interceptor's holder. 12037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Retrieve a field from field's holder. 12047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateFastPropertyLoad(masm(), eax, holder_reg, 12057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch lookup->holder(), lookup->GetFieldIndex()); 12067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ ret(0); 12077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 12087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // We found CALLBACKS property in prototype chain of interceptor's 12097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // holder. 12107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(lookup->type() == CALLBACKS); 12117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(lookup->GetCallbackObject()->IsAccessorInfo()); 12127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); 12137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(callback != NULL); 12147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(callback->getter() != NULL); 12157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Tail call to runtime. 12177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Important invariant in CALLBACKS case: the code above must be 12187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // structured to never clobber |receiver| register. 12197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(scratch2); // return address 12207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(receiver); 12217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(holder_reg); 12227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(holder_reg, Immediate(Handle<AccessorInfo>(callback))); 12237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(holder_reg); 12247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset)); 12257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(name_reg); 12267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(scratch2); // restore return address 12277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ExternalReference ref = 12297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ExternalReference(IC_Utility(IC::kLoadCallbackProperty)); 12307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ TailCallExternalReference(ref, 5, 1); 12317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 12327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { // !compile_followup_inline 12337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Call the runtime system to load the interceptor. 12347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps haven't changed. 12357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register holder_reg = 12367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch CheckPrototypes(object, receiver, interceptor_holder, 12373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch1, scratch2, scratch3, name, miss); 12387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(scratch2); // save old return address 12397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch PushInterceptorArguments(masm(), receiver, holder_reg, 12407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch name_reg, interceptor_holder); 12417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(scratch2); // restore old return address 12427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ExternalReference ref = ExternalReference( 12447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch IC_Utility(IC::kLoadPropertyWithInterceptorForLoad)); 12457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ TailCallExternalReference(ref, 5, 1); 12467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid CallStubCompiler::GenerateNameCheck(String* name, Label* miss) { 12517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (kind_ == Code::KEYED_CALL_IC) { 12527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ cmp(Operand(ecx), Immediate(Handle<String>(name))); 12537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(not_equal, miss, not_taken); 12547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 12557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 12567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 125859151504615d929945dc59db37bf1166937748c6Steve Blockvoid CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, 125959151504615d929945dc59db37bf1166937748c6Steve Block JSObject* holder, 126059151504615d929945dc59db37bf1166937748c6Steve Block String* name, 126159151504615d929945dc59db37bf1166937748c6Steve Block Label* miss) { 126259151504615d929945dc59db37bf1166937748c6Steve Block ASSERT(holder->IsGlobalObject()); 126359151504615d929945dc59db37bf1166937748c6Steve Block 126459151504615d929945dc59db37bf1166937748c6Steve Block // Get the number of arguments. 126559151504615d929945dc59db37bf1166937748c6Steve Block const int argc = arguments().immediate(); 126659151504615d929945dc59db37bf1166937748c6Steve Block 126759151504615d929945dc59db37bf1166937748c6Steve Block // Get the receiver from the stack. 126859151504615d929945dc59db37bf1166937748c6Steve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 126959151504615d929945dc59db37bf1166937748c6Steve Block 127059151504615d929945dc59db37bf1166937748c6Steve Block // If the object is the holder then we know that it's a global 127159151504615d929945dc59db37bf1166937748c6Steve Block // object which can only happen for contextual calls. In this case, 127259151504615d929945dc59db37bf1166937748c6Steve Block // the receiver cannot be a smi. 127359151504615d929945dc59db37bf1166937748c6Steve Block if (object != holder) { 127459151504615d929945dc59db37bf1166937748c6Steve Block __ test(edx, Immediate(kSmiTagMask)); 127559151504615d929945dc59db37bf1166937748c6Steve Block __ j(zero, miss, not_taken); 127659151504615d929945dc59db37bf1166937748c6Steve Block } 127759151504615d929945dc59db37bf1166937748c6Steve Block 127859151504615d929945dc59db37bf1166937748c6Steve Block // Check that the maps haven't changed. 127959151504615d929945dc59db37bf1166937748c6Steve Block CheckPrototypes(object, edx, holder, ebx, eax, edi, name, miss); 128059151504615d929945dc59db37bf1166937748c6Steve Block} 128159151504615d929945dc59db37bf1166937748c6Steve Block 128259151504615d929945dc59db37bf1166937748c6Steve Block 128359151504615d929945dc59db37bf1166937748c6Steve Blockvoid CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, 128459151504615d929945dc59db37bf1166937748c6Steve Block JSFunction* function, 128559151504615d929945dc59db37bf1166937748c6Steve Block Label* miss) { 128659151504615d929945dc59db37bf1166937748c6Steve Block // Get the value from the cell. 128759151504615d929945dc59db37bf1166937748c6Steve Block __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell))); 128859151504615d929945dc59db37bf1166937748c6Steve Block __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); 128959151504615d929945dc59db37bf1166937748c6Steve Block 129059151504615d929945dc59db37bf1166937748c6Steve Block // Check that the cell contains the same function. 129159151504615d929945dc59db37bf1166937748c6Steve Block if (Heap::InNewSpace(function)) { 129259151504615d929945dc59db37bf1166937748c6Steve Block // We can't embed a pointer to a function in new space so we have 129359151504615d929945dc59db37bf1166937748c6Steve Block // to verify that the shared function info is unchanged. This has 129459151504615d929945dc59db37bf1166937748c6Steve Block // the nice side effect that multiple closures based on the same 129559151504615d929945dc59db37bf1166937748c6Steve Block // function can all use this call IC. Before we load through the 129659151504615d929945dc59db37bf1166937748c6Steve Block // function, we have to verify that it still is a function. 129759151504615d929945dc59db37bf1166937748c6Steve Block __ test(edi, Immediate(kSmiTagMask)); 129859151504615d929945dc59db37bf1166937748c6Steve Block __ j(zero, miss, not_taken); 129959151504615d929945dc59db37bf1166937748c6Steve Block __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); 130059151504615d929945dc59db37bf1166937748c6Steve Block __ j(not_equal, miss, not_taken); 130159151504615d929945dc59db37bf1166937748c6Steve Block 130259151504615d929945dc59db37bf1166937748c6Steve Block // Check the shared function info. Make sure it hasn't changed. 130359151504615d929945dc59db37bf1166937748c6Steve Block __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), 130459151504615d929945dc59db37bf1166937748c6Steve Block Immediate(Handle<SharedFunctionInfo>(function->shared()))); 130559151504615d929945dc59db37bf1166937748c6Steve Block __ j(not_equal, miss, not_taken); 130659151504615d929945dc59db37bf1166937748c6Steve Block } else { 130759151504615d929945dc59db37bf1166937748c6Steve Block __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function))); 130859151504615d929945dc59db37bf1166937748c6Steve Block __ j(not_equal, miss, not_taken); 130959151504615d929945dc59db37bf1166937748c6Steve Block } 131059151504615d929945dc59db37bf1166937748c6Steve Block} 131159151504615d929945dc59db37bf1166937748c6Steve Block 131259151504615d929945dc59db37bf1166937748c6Steve Block 1313bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochObject* CallStubCompiler::GenerateMissBranch() { 1314bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Object* obj = StubCache::ComputeCallMiss(arguments().immediate(), kind_); 1315bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (obj->IsFailure()) return obj; 1316bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); 1317bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch return obj; 13187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 13197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1321402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuObject* CallStubCompiler::CompileCallField(JSObject* object, 1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index, 1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name) { 1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1326e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 1327e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 1328e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1329e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 1330e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateNameCheck(name, &miss); 13357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver from the stack. 1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(edx, Immediate(kSmiTagMask)); 1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &miss, not_taken); 1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do the right check and compute the holder register. 13453bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register reg = CheckPrototypes(object, edx, holder, ebx, eax, edi, 13463bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch name, &miss); 1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateFastPropertyLoad(masm(), edi, reg, holder, index); 1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the function really is a function. 1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(edi, Immediate(kSmiTagMask)); 1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &miss, not_taken); 1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); 1354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss, not_taken); 1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack with the global proxy if 1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // necessary. 1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsGlobalObject()) { 1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the function. 1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeFunction(edi, arguments(), JUMP_FUNCTION); 1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 1368bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Object* obj = GenerateMissBranch(); 1369bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (obj->IsFailure()) return obj; 1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(FIELD, name); 1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13766ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockObject* CallStubCompiler::CompileArrayPushCall(Object* object, 13776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSObject* holder, 137859151504615d929945dc59db37bf1166937748c6Steve Block JSGlobalPropertyCell* cell, 13796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSFunction* function, 138059151504615d929945dc59db37bf1166937748c6Steve Block String* name) { 13816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 13826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : name 13836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[0] : return address 13846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[(argc - n) * 4] : arg[n] (zero-based) 13856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ... 13866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[(argc + 1) * 4] : receiver 13876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 13886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // If object is not an array, bail out to regular call. 139059151504615d929945dc59db37bf1166937748c6Steve Block if (!object->IsJSArray() || cell != NULL) return Heap::undefined_value(); 13916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss; 13936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateNameCheck(name, &miss); 13957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the receiver from the stack. 13976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int argc = arguments().immediate(); 13986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 13996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the receiver isn't a smi. 14016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(edx, Immediate(kSmiTagMask)); 14026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(zero, &miss); 14036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CheckPrototypes(JSObject::cast(object), edx, 14056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block holder, ebx, 14063bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch eax, edi, name, &miss); 14076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (argc == 0) { 14096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Noop, return the length. 14106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); 14116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret((argc + 1) * kPointerSize); 14126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 1413756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label call_builtin; 1414756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 14156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the elements array of the object. 14166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); 14176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1418756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Check that the elements are in fast mode and writable. 14196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 14206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Immediate(Factory::fixed_array_map())); 1421756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ j(not_equal, &call_builtin); 14226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (argc == 1) { // Otherwise fall through to call builtin. 1424756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label exit, with_write_barrier, attempt_to_grow_elements; 14256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the array's length into eax and calculate new length. 14276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); 14286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block STATIC_ASSERT(kSmiTagSize == 1); 14296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block STATIC_ASSERT(kSmiTag == 0); 14306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ add(Operand(eax), Immediate(Smi::FromInt(argc))); 14316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the element's length into ecx. 14336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ecx, FieldOperand(ebx, FixedArray::kLengthOffset)); 14346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check if we could survive without allocation. 14366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(eax, Operand(ecx)); 14376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(greater, &attempt_to_grow_elements); 14386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Save new length. 14406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); 14416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Push the element. 14436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ lea(edx, FieldOperand(ebx, 14446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block eax, times_half_pointer_size, 14456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FixedArray::kHeaderSize - argc * kPointerSize)); 14466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ecx, Operand(esp, argc * kPointerSize)); 14476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(Operand(edx, 0), ecx); 14486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check if value is a smi. 14506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(ecx, Immediate(kSmiTagMask)); 14517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ j(not_zero, &with_write_barrier); 14526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&exit); 14546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret((argc + 1) * kPointerSize); 14556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&with_write_barrier); 14576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ InNewSpace(ebx, ecx, equal, &exit); 14596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ RecordWriteHelper(ebx, edx, ecx); 14616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret((argc + 1) * kPointerSize); 14626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&attempt_to_grow_elements); 14646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference new_space_allocation_top = 14656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference::new_space_allocation_top_address(); 14666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference new_space_allocation_limit = 14676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference::new_space_allocation_limit_address(); 14686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kAllocationDelta = 4; 14706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Load top. 14716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ecx, Operand::StaticVariable(new_space_allocation_top)); 14726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check if it's the end of elements. 14746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ lea(edx, FieldOperand(ebx, 14756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block eax, times_half_pointer_size, 14766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FixedArray::kHeaderSize - argc * kPointerSize)); 14776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(edx, Operand(ecx)); 14786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_equal, &call_builtin); 14796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ add(Operand(ecx), Immediate(kAllocationDelta * kPointerSize)); 14806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(ecx, Operand::StaticVariable(new_space_allocation_limit)); 14816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(above, &call_builtin); 14826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // We fit and could grow elements. 14846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(Operand::StaticVariable(new_space_allocation_top), ecx); 14856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ecx, Operand(esp, argc * kPointerSize)); 14866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Push the argument... 14886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(Operand(edx, 0), ecx); 14896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ... and fill the rest with holes. 14906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (int i = 1; i < kAllocationDelta; i++) { 14916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(Operand(edx, i * kPointerSize), 14926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Immediate(Factory::the_hole_value())); 14936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 14946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Restore receiver to edx as finish sequence assumes it's here. 14966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 14976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Increment element's and array's sizes. 14996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ add(FieldOperand(ebx, FixedArray::kLengthOffset), 15007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Immediate(Smi::FromInt(kAllocationDelta))); 15016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); 15026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Elements are in new space, so write barrier is not required. 15046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret((argc + 1) * kPointerSize); 15056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 15066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1507756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ bind(&call_builtin); 15086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush), 15096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block argc + 1, 15106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1); 15116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 15126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss); 1514bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Object* obj = GenerateMissBranch(); 1515bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (obj->IsFailure()) return obj; 15166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return the generated code. 151825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen return GetCode(function); 15196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 15206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15226ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockObject* CallStubCompiler::CompileArrayPopCall(Object* object, 15236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSObject* holder, 152459151504615d929945dc59db37bf1166937748c6Steve Block JSGlobalPropertyCell* cell, 15256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSFunction* function, 152659151504615d929945dc59db37bf1166937748c6Steve Block String* name) { 15276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 15286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : name 15296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[0] : return address 15306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[(argc - n) * 4] : arg[n] (zero-based) 15316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ... 15326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[(argc + 1) * 4] : receiver 15336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 15346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // If object is not an array, bail out to regular call. 153659151504615d929945dc59db37bf1166937748c6Steve Block if (!object->IsJSArray() || cell != NULL) return Heap::undefined_value(); 15376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss, return_undefined, call_builtin; 15396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateNameCheck(name, &miss); 15417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 15426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the receiver from the stack. 15436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int argc = arguments().immediate(); 15446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 15456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the receiver isn't a smi. 15476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(edx, Immediate(kSmiTagMask)); 15486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(zero, &miss); 15496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CheckPrototypes(JSObject::cast(object), edx, 15506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block holder, ebx, 15513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch eax, edi, name, &miss); 15526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the elements array of the object. 15546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); 15556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1556756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Check that the elements are in fast mode and writable. 15576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 15586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Immediate(Factory::fixed_array_map())); 1559756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ j(not_equal, &call_builtin); 15606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the array's length into ecx and calculate new length. 15626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ecx, FieldOperand(edx, JSArray::kLengthOffset)); 15636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ sub(Operand(ecx), Immediate(Smi::FromInt(1))); 15646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(negative, &return_undefined); 15656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the last element. 15676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block STATIC_ASSERT(kSmiTagSize == 1); 15686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block STATIC_ASSERT(kSmiTag == 0); 15696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(eax, FieldOperand(ebx, 15706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ecx, times_half_pointer_size, 15716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FixedArray::kHeaderSize)); 15726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(Operand(eax), Immediate(Factory::the_hole_value())); 15736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(equal, &call_builtin); 15746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Set the array's length. 15766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(FieldOperand(edx, JSArray::kLengthOffset), ecx); 15776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Fill with the hole. 15796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(FieldOperand(ebx, 15806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ecx, times_half_pointer_size, 15816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FixedArray::kHeaderSize), 15826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Immediate(Factory::the_hole_value())); 15836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret((argc + 1) * kPointerSize); 15846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&return_undefined); 15866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(eax, Immediate(Factory::undefined_value())); 15876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret((argc + 1) * kPointerSize); 15886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&call_builtin); 15906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop), 15916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block argc + 1, 15926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1); 15936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss); 1595bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Object* obj = GenerateMissBranch(); 1596bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (obj->IsFailure()) return obj; 15977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 15987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Return the generated code. 15997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch return GetCode(function); 16007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 16017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 160359151504615d929945dc59db37bf1166937748c6Steve BlockObject* CallStubCompiler::CompileStringCharCodeAtCall( 160459151504615d929945dc59db37bf1166937748c6Steve Block Object* object, 160559151504615d929945dc59db37bf1166937748c6Steve Block JSObject* holder, 160659151504615d929945dc59db37bf1166937748c6Steve Block JSGlobalPropertyCell* cell, 160759151504615d929945dc59db37bf1166937748c6Steve Block JSFunction* function, 160859151504615d929945dc59db37bf1166937748c6Steve Block String* name) { 16097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------- S t a t e ------------- 16107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ecx : function name 16117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[0] : return address 16127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc - n) * 4] : arg[n] (zero-based) 16137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ... 16147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc + 1) * 4] : receiver 16157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------------------------------- 16167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1617756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // If object is not a string, bail out to regular call. 161859151504615d929945dc59db37bf1166937748c6Steve Block if (!object->IsString() || cell != NULL) return Heap::undefined_value(); 1619756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 16207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch const int argc = arguments().immediate(); 16217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label miss; 16237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 16247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateNameCheck(name, &miss); 16257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps starting from the prototype haven't changed. 16277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype(masm(), 16287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Context::STRING_FUNCTION_INDEX, 16297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch eax); 1630756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick ASSERT(object != holder); 16317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, 16323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ebx, edx, edi, name, &miss); 16337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register receiver = ebx; 16357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = edi; 16367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch = edx; 16377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = eax; 16387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); 16397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (argc > 0) { 16407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); 16417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 16427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Set(index, Immediate(Factory::undefined_value())); 16437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 16447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharCodeAtGenerator char_code_at_generator(receiver, 16467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch index, 16477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch, 16487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch result, 16497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &miss, // When not a string. 16507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &miss, // When not a number. 16517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &index_out_of_range, 16527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch STRING_INDEX_IS_NUMBER); 16537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch char_code_at_generator.GenerateFast(masm()); 16547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ ret((argc + 1) * kPointerSize); 16557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ICRuntimeCallHelper call_helper; 16577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch char_code_at_generator.GenerateSlow(masm(), call_helper); 16587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_out_of_range); 16607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Set(eax, Immediate(Factory::nan_value())); 16617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ ret((argc + 1) * kPointerSize); 16627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&miss); 1664bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Object* obj = GenerateMissBranch(); 1665bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (obj->IsFailure()) return obj; 16667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Return the generated code. 16687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch return GetCode(function); 16697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 16707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen MurdochObject* CallStubCompiler::CompileStringCharAtCall(Object* object, 16737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch JSObject* holder, 167459151504615d929945dc59db37bf1166937748c6Steve Block JSGlobalPropertyCell* cell, 16757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch JSFunction* function, 167659151504615d929945dc59db37bf1166937748c6Steve Block String* name) { 16777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------- S t a t e ------------- 16787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ecx : function name 16797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[0] : return address 16807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc - n) * 4] : arg[n] (zero-based) 16817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- ... 16827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // -- esp[(argc + 1) * 4] : receiver 16837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // ----------------------------------- 16847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1685756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // If object is not a string, bail out to regular call. 168659151504615d929945dc59db37bf1166937748c6Steve Block if (!object->IsString() || cell != NULL) return Heap::undefined_value(); 1687756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 16887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch const int argc = arguments().immediate(); 16897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label miss; 16917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 16927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateNameCheck(name, &miss); 16947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps starting from the prototype haven't changed. 16967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype(masm(), 16977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Context::STRING_FUNCTION_INDEX, 16987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch eax); 1699756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick ASSERT(object != holder); 17007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, 17013bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ebx, edx, edi, name, &miss); 17027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register receiver = eax; 17047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = edi; 17057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch1 = ebx; 17067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register scratch2 = edx; 17077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = eax; 17087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); 17097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (argc > 0) { 17107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); 17117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 17127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Set(index, Immediate(Factory::undefined_value())); 17137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 17147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharAtGenerator char_at_generator(receiver, 17167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch index, 17177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch1, 17187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch2, 17197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch result, 17207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &miss, // When not a string. 17217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &miss, // When not a number. 17227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &index_out_of_range, 17237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch STRING_INDEX_IS_NUMBER); 17247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch char_at_generator.GenerateFast(masm()); 17257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ ret((argc + 1) * kPointerSize); 17267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ICRuntimeCallHelper call_helper; 17287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch char_at_generator.GenerateSlow(masm(), call_helper); 17297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_out_of_range); 17317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Set(eax, Immediate(Factory::empty_string())); 17327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ ret((argc + 1) * kPointerSize); 17337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&miss); 1735bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Object* obj = GenerateMissBranch(); 1736bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (obj->IsFailure()) return obj; 17376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return the generated code. 173925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen return GetCode(function); 17406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 17416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 174359151504615d929945dc59db37bf1166937748c6Steve BlockObject* CallStubCompiler::CompileStringFromCharCodeCall( 174459151504615d929945dc59db37bf1166937748c6Steve Block Object* object, 174559151504615d929945dc59db37bf1166937748c6Steve Block JSObject* holder, 174659151504615d929945dc59db37bf1166937748c6Steve Block JSGlobalPropertyCell* cell, 174759151504615d929945dc59db37bf1166937748c6Steve Block JSFunction* function, 174859151504615d929945dc59db37bf1166937748c6Steve Block String* name) { 174959151504615d929945dc59db37bf1166937748c6Steve Block // ----------- S t a t e ------------- 175059151504615d929945dc59db37bf1166937748c6Steve Block // -- ecx : function name 175159151504615d929945dc59db37bf1166937748c6Steve Block // -- esp[0] : return address 175259151504615d929945dc59db37bf1166937748c6Steve Block // -- esp[(argc - n) * 4] : arg[n] (zero-based) 175359151504615d929945dc59db37bf1166937748c6Steve Block // -- ... 175459151504615d929945dc59db37bf1166937748c6Steve Block // -- esp[(argc + 1) * 4] : receiver 175559151504615d929945dc59db37bf1166937748c6Steve Block // ----------------------------------- 175659151504615d929945dc59db37bf1166937748c6Steve Block 175759151504615d929945dc59db37bf1166937748c6Steve Block const int argc = arguments().immediate(); 175859151504615d929945dc59db37bf1166937748c6Steve Block 175959151504615d929945dc59db37bf1166937748c6Steve Block // If the object is not a JSObject or we got an unexpected number of 176059151504615d929945dc59db37bf1166937748c6Steve Block // arguments, bail out to the regular call. 176159151504615d929945dc59db37bf1166937748c6Steve Block if (!object->IsJSObject() || argc != 1) return Heap::undefined_value(); 176259151504615d929945dc59db37bf1166937748c6Steve Block 176359151504615d929945dc59db37bf1166937748c6Steve Block Label miss; 176459151504615d929945dc59db37bf1166937748c6Steve Block GenerateNameCheck(name, &miss); 176559151504615d929945dc59db37bf1166937748c6Steve Block 176659151504615d929945dc59db37bf1166937748c6Steve Block if (cell == NULL) { 176759151504615d929945dc59db37bf1166937748c6Steve Block __ mov(edx, Operand(esp, 2 * kPointerSize)); 176859151504615d929945dc59db37bf1166937748c6Steve Block 176959151504615d929945dc59db37bf1166937748c6Steve Block STATIC_ASSERT(kSmiTag == 0); 177059151504615d929945dc59db37bf1166937748c6Steve Block __ test(edx, Immediate(kSmiTagMask)); 177159151504615d929945dc59db37bf1166937748c6Steve Block __ j(zero, &miss); 177259151504615d929945dc59db37bf1166937748c6Steve Block 177359151504615d929945dc59db37bf1166937748c6Steve Block CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, 177459151504615d929945dc59db37bf1166937748c6Steve Block &miss); 177559151504615d929945dc59db37bf1166937748c6Steve Block } else { 177659151504615d929945dc59db37bf1166937748c6Steve Block ASSERT(cell->value() == function); 177759151504615d929945dc59db37bf1166937748c6Steve Block GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); 177859151504615d929945dc59db37bf1166937748c6Steve Block GenerateLoadFunctionFromCell(cell, function, &miss); 177959151504615d929945dc59db37bf1166937748c6Steve Block } 178059151504615d929945dc59db37bf1166937748c6Steve Block 178159151504615d929945dc59db37bf1166937748c6Steve Block // Load the char code argument. 178259151504615d929945dc59db37bf1166937748c6Steve Block Register code = ebx; 178359151504615d929945dc59db37bf1166937748c6Steve Block __ mov(code, Operand(esp, 1 * kPointerSize)); 178459151504615d929945dc59db37bf1166937748c6Steve Block 178559151504615d929945dc59db37bf1166937748c6Steve Block // Check the code is a smi. 178659151504615d929945dc59db37bf1166937748c6Steve Block Label slow; 178759151504615d929945dc59db37bf1166937748c6Steve Block STATIC_ASSERT(kSmiTag == 0); 178859151504615d929945dc59db37bf1166937748c6Steve Block __ test(code, Immediate(kSmiTagMask)); 178959151504615d929945dc59db37bf1166937748c6Steve Block __ j(not_zero, &slow); 179059151504615d929945dc59db37bf1166937748c6Steve Block 179159151504615d929945dc59db37bf1166937748c6Steve Block // Convert the smi code to uint16. 179259151504615d929945dc59db37bf1166937748c6Steve Block __ and_(code, Immediate(Smi::FromInt(0xffff))); 179359151504615d929945dc59db37bf1166937748c6Steve Block 179459151504615d929945dc59db37bf1166937748c6Steve Block StringCharFromCodeGenerator char_from_code_generator(code, eax); 179559151504615d929945dc59db37bf1166937748c6Steve Block char_from_code_generator.GenerateFast(masm()); 179659151504615d929945dc59db37bf1166937748c6Steve Block __ ret(2 * kPointerSize); 179759151504615d929945dc59db37bf1166937748c6Steve Block 179859151504615d929945dc59db37bf1166937748c6Steve Block ICRuntimeCallHelper call_helper; 179959151504615d929945dc59db37bf1166937748c6Steve Block char_from_code_generator.GenerateSlow(masm(), call_helper); 180059151504615d929945dc59db37bf1166937748c6Steve Block 180159151504615d929945dc59db37bf1166937748c6Steve Block // Tail call the full function. We do not have to patch the receiver 180259151504615d929945dc59db37bf1166937748c6Steve Block // because the function makes no use of it. 180359151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&slow); 180459151504615d929945dc59db37bf1166937748c6Steve Block __ InvokeFunction(function, arguments(), JUMP_FUNCTION); 180559151504615d929945dc59db37bf1166937748c6Steve Block 180659151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&miss); 180759151504615d929945dc59db37bf1166937748c6Steve Block // ecx: function name. 180859151504615d929945dc59db37bf1166937748c6Steve Block Object* obj = GenerateMissBranch(); 180959151504615d929945dc59db37bf1166937748c6Steve Block if (obj->IsFailure()) return obj; 181059151504615d929945dc59db37bf1166937748c6Steve Block 181159151504615d929945dc59db37bf1166937748c6Steve Block // Return the generated code. 181259151504615d929945dc59db37bf1166937748c6Steve Block return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); 181359151504615d929945dc59db37bf1166937748c6Steve Block} 181459151504615d929945dc59db37bf1166937748c6Steve Block 181559151504615d929945dc59db37bf1166937748c6Steve Block 1816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* CallStubCompiler::CompileCallConstant(Object* object, 1817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 1818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSFunction* function, 1819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name, 1820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckType check) { 1821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1822e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 1823e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 1824e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1825e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 1826e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 1827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 18286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SharedFunctionInfo* function_info = function->shared(); 18306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (function_info->HasCustomCallGenerator()) { 183125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen const int id = function_info->custom_call_generator_id(); 183259151504615d929945dc59db37bf1166937748c6Steve Block Object* result = CompileCustomCall( 183359151504615d929945dc59db37bf1166937748c6Steve Block id, object, holder, NULL, function, name); 18346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // undefined means bail out to regular compiler. 183559151504615d929945dc59db37bf1166937748c6Steve Block if (!result->IsUndefined()) return result; 18366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 18376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss_in_smi_check; 1839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 18407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateNameCheck(name, &miss_in_smi_check); 18417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver from the stack. 1843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 1844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 1847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check != NUMBER_CHECK) { 1848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(edx, Immediate(kSmiTagMask)); 18496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(zero, &miss_in_smi_check, not_taken); 1850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure that it's okay not to patch the on stack receiver 1853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // unless we're doing a receiver map check. 1854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); 1855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1856402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu CallOptimization optimization(function); 1857402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int depth = kInvalidProtoDepth; 18586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss; 1859402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (check) { 1861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case RECEIVER_MAP_CHECK: 1862402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ IncrementCounter(&Counters::call_const, 1); 1863402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1864402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (optimization.is_simple_api_call() && !object->IsGlobalObject()) { 1865402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu depth = optimization.GetPrototypeDepthOfExpectedType( 1866402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu JSObject::cast(object), holder); 1867402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1868402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1869402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (depth != kInvalidProtoDepth) { 1870402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ IncrementCounter(&Counters::call_const_fast_api, 1); 1871402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ReserveSpaceForFastApiCall(masm(), eax); 1872402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1873402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 1875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPrototypes(JSObject::cast(object), edx, holder, 18763bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ebx, eax, edi, name, depth, &miss); 1877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack with the global proxy if 1879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // necessary. 1880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsGlobalObject()) { 1881402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(depth == kInvalidProtoDepth); 1882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 1883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 1884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case STRING_CHECK: 1888e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!function->IsBuiltin()) { 1889e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Calling non-builtins with a value as receiver requires boxing. 1890e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(&miss); 1891e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 1892e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the object is a string or a symbol. 18937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax); 1894e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(above_equal, &miss, not_taken); 1895e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the maps starting from the prototype haven't changed. 18967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype( 18977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch masm(), Context::STRING_FUNCTION_INDEX, eax); 1898e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, 18993bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ebx, edx, edi, name, &miss); 1900e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case NUMBER_CHECK: { 1904e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!function->IsBuiltin()) { 1905e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Calling non-builtins with a value as receiver requires boxing. 1906e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(&miss); 1907e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 1908e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label fast; 1909e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the object is a smi or a heap number. 1910e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ test(edx, Immediate(kSmiTagMask)); 1911e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(zero, &fast, taken); 1912e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); 1913e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_equal, &miss, not_taken); 1914e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&fast); 1915e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the maps starting from the prototype haven't changed. 19167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype( 19177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch masm(), Context::NUMBER_FUNCTION_INDEX, eax); 1918e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, 19193bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ebx, edx, edi, name, &miss); 1920e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case BOOLEAN_CHECK: { 1925e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!function->IsBuiltin()) { 1926e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Calling non-builtins with a value as receiver requires boxing. 1927e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(&miss); 1928e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 1929e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label fast; 1930e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the object is a boolean. 1931e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(edx, Factory::true_value()); 1932e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(equal, &fast, taken); 1933e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(edx, Factory::false_value()); 1934e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(not_equal, &miss, not_taken); 1935e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&fast); 1936e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the maps starting from the prototype haven't changed. 19377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype( 19387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch masm(), Context::BOOLEAN_FUNCTION_INDEX, eax); 1939e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, 19403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ebx, edx, edi, name, &miss); 1941e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 1946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 1947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1949402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (depth != kInvalidProtoDepth) { 1950402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateFastApiCall(masm(), optimization, argc); 1951402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 1952402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ InvokeFunction(function, arguments(), JUMP_FUNCTION); 1953402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 1956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 1957402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (depth != kInvalidProtoDepth) { 1958402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu FreeSpaceForFastApiCall(masm(), eax); 1959402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 19606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss_in_smi_check); 1961bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Object* obj = GenerateMissBranch(); 1962bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (obj->IsFailure()) return obj; 1963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 196525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen return GetCode(function); 1966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1969402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, 1970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 1971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name) { 1972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1973e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 1974e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 1975e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1976e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 1977e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 1978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 1980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 19817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateNameCheck(name, &miss); 19827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the number of arguments. 1984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 1985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupResult lookup; 1987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupPostInterceptor(holder, name, &lookup); 1988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver from the stack. 1990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1992402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu CallInterceptorCompiler compiler(this, arguments(), ecx); 1993402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu compiler.Compile(masm(), 1994402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu object, 1995402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu holder, 1996402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu name, 1997402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu &lookup, 1998402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu edx, 1999402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ebx, 2000402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu edi, 20013bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch eax, 2002402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu &miss); 2003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore receiver. 2005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 2006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the function really is a function. 2008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(eax, Immediate(kSmiTagMask)); 2009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &miss, not_taken); 2010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); 2011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss, not_taken); 2012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack with the global proxy if 2014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // necessary. 2015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsGlobalObject()) { 2016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 2017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 2018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the function. 2021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edi, eax); 2022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeFunction(edi, arguments(), JUMP_FUNCTION); 2023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle load cache miss. 2025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2026bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Object* obj = GenerateMissBranch(); 2027bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (obj->IsFailure()) return obj; 2028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* CallStubCompiler::CompileCallGlobal(JSObject* object, 2035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalObject* holder, 2036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSGlobalPropertyCell* cell, 2037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSFunction* function, 2038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name) { 2039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2040e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ecx : name 2041e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 2042e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc - n) * 4] : arg[n] (zero-based) 2043e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 2044e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[(argc + 1) * 4] : receiver 2045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 204659151504615d929945dc59db37bf1166937748c6Steve Block 204759151504615d929945dc59db37bf1166937748c6Steve Block SharedFunctionInfo* function_info = function->shared(); 204859151504615d929945dc59db37bf1166937748c6Steve Block if (function_info->HasCustomCallGenerator()) { 204959151504615d929945dc59db37bf1166937748c6Steve Block const int id = function_info->custom_call_generator_id(); 205059151504615d929945dc59db37bf1166937748c6Steve Block Object* result = CompileCustomCall( 205159151504615d929945dc59db37bf1166937748c6Steve Block id, object, holder, cell, function, name); 205259151504615d929945dc59db37bf1166937748c6Steve Block // undefined means bail out to regular compiler. 205359151504615d929945dc59db37bf1166937748c6Steve Block if (!result->IsUndefined()) return result; 205459151504615d929945dc59db37bf1166937748c6Steve Block } 205559151504615d929945dc59db37bf1166937748c6Steve Block 2056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 20587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateNameCheck(name, &miss); 20597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the number of arguments. 2061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 2062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 206359151504615d929945dc59db37bf1166937748c6Steve Block GenerateGlobalReceiverCheck(object, holder, name, &miss); 2064e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 206559151504615d929945dc59db37bf1166937748c6Steve Block GenerateLoadFunctionFromCell(cell, function, &miss); 2066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack with the global proxy. 2068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsGlobalObject()) { 2069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 2070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 2071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Setup the context (function already in edi). 2074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 2075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the cached code (tail call). 2077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::call_global_inline, 1); 2078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(function->is_compiled()); 2079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> code(function->code()); 2080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount expected(function->shared()->formal_parameter_count()); 2081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeCode(code, expected, arguments(), 2082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::CODE_TARGET, JUMP_FUNCTION); 2083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 2085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::call_global_inline_miss, 1); 2087bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Object* obj = GenerateMissBranch(); 2088bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if (obj->IsFailure()) return obj; 2089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(NORMAL, name); 2092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* StoreStubCompiler::CompileStoreField(JSObject* object, 2096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index, 2097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Map* transition, 2098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name) { 2099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 2101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 21024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- edx : receiver 2103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Generate store field code. Trashes the name register. 2108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateStoreField(masm(), 2109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object, 2110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block index, 2111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block transition, 21124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke edx, ecx, ebx, 2113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &miss); 2114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ecx, Immediate(Handle<String>(name))); // restore name 2118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); 2119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(ic, RelocInfo::CODE_TARGET); 2120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); 2123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* StoreStubCompiler::CompileStoreCallback(JSObject* object, 2127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AccessorInfo* callback, 2128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name) { 2129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 2131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 21324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- edx : receiver 2133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object isn't a smi. 21384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ test(edx, Immediate(kSmiTagMask)); 2139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &miss, not_taken); 2140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the object hasn't changed. 21424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ cmp(FieldOperand(edx, HeapObject::kMapOffset), 2143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(Handle<Map>(object->map()))); 2144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss, not_taken); 2145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform global security token check if needed. 2147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsJSGlobalProxy()) { 21484515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CheckAccessGlobalProxy(edx, ebx, &miss); 2149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stub never generated for non-global objects that require access 2152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks. 2153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 2154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); // remove the return address 21564515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(edx); // receiver 2157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(Immediate(Handle<AccessorInfo>(callback))); // callback info 2158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); // name 2159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(eax); // value 2160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); // restore return address 2161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to the runtime system. 2163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference store_callback_property = 2164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference(IC_Utility(IC::kStoreCallbackProperty)); 21656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(store_callback_property, 4, 1); 2166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); 2170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(ic, RelocInfo::CODE_TARGET); 2171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, 2178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name) { 2179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 2181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 21824515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- edx : receiver 2183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object isn't a smi. 21884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ test(edx, Immediate(kSmiTagMask)); 2189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &miss, not_taken); 2190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the object hasn't changed. 21924515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ cmp(FieldOperand(edx, HeapObject::kMapOffset), 2193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(Handle<Map>(receiver->map()))); 2194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss, not_taken); 2195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform global security token check if needed. 2197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (receiver->IsJSGlobalProxy()) { 21984515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CheckAccessGlobalProxy(edx, ebx, &miss); 2199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stub never generated for non-global objects that require access 2202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks. 2203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); 2204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); // remove the return address 22064515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(edx); // receiver 2207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); // name 2208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(eax); // value 2209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); // restore return address 2210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to the runtime system. 2212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference store_ic_property = 2213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference(IC_Utility(IC::kStoreInterceptorProperty)); 22146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(store_ic_property, 3, 1); 2215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); 2219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(ic, RelocInfo::CODE_TARGET); 2220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, 2227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSGlobalPropertyCell* cell, 2228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name) { 2229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 2231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 22324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- edx : receiver 2233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the global has not changed. 22384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ cmp(FieldOperand(edx, HeapObject::kMapOffset), 2239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(Handle<Map>(object->map()))); 2240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss, not_taken); 2241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Store the value in the cell. 2243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ecx, Immediate(Handle<JSGlobalPropertyCell>(cell))); 2244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(FieldOperand(ecx, JSGlobalPropertyCell::kValueOffset), eax); 2245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the value (register eax). 2247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::named_store_global_inline, 1); 2248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 2249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::named_store_global_inline_miss, 1); 2253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); 2254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(ic, RelocInfo::CODE_TARGET); 2255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(NORMAL, name); 2258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, 2262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index, 2263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Map* transition, 2264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name) { 2265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : value 22676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : key 22686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- edx : receiver 2269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::keyed_store_field, 1); 2274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 2276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(Operand(ecx), Immediate(Handle<String>(name))); 2277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss, not_taken); 2278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Generate store field code. Trashes the name register. 2280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateStoreField(masm(), 2281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object, 2282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block index, 2283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block transition, 2284402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu edx, ecx, ebx, 2285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &miss); 2286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ DecrementCounter(&Counters::keyed_store_field, 1); 2290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss)); 2291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(ic, RelocInfo::CODE_TARGET); 2292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); 2295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 22986ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockObject* LoadStubCompiler::CompileLoadNonexistent(String* name, 22996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSObject* object, 23006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSObject* last) { 23016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 23026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- eax : receiver 23036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ecx : name 23046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- esp[0] : return address 23056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 23066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss; 23076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 23086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the receiver isn't a smi. 23096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ test(eax, Immediate(kSmiTagMask)); 23106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(zero, &miss, not_taken); 23116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 23128defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(last->IsGlobalObject() || last->HasFastProperties()); 23138defd9ff6930b4e24729971a61cf7469daf119beSteve Block 23146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check the maps of the full prototype chain. Also check that 23156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // global property cells up to (but not including) the last object 23166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // in the prototype chain are empty. 23173bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss); 23186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 23196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // If the last object in the prototype chain is a global object, 23206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // check that the global property cell is empty. 23216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (last->IsGlobalObject()) { 23226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Object* cell = GenerateCheckPropertyCell(masm(), 23236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GlobalObject::cast(last), 23246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block name, 23256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block edx, 23266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block &miss); 23276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (cell->IsFailure()) return cell; 23286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 23296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 23306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return undefined if maps of the full prototype chain are still the 23316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // same and no global property with this name contains a value. 23326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(eax, Factory::undefined_value()); 23336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ret(0); 23346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 23356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss); 23366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 23376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 23386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return the generated code. 23396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return GetCode(NONEXISTENT, Heap::empty_string()); 23406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 23416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* LoadStubCompiler::CompileLoadField(JSObject* object, 2344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 2345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index, 2346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name) { 2347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2348402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 2349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 2350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23543bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch GenerateLoadField(object, holder, eax, ebx, edx, edi, index, name, &miss); 2355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(FIELD, name); 2360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2363e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeObject* LoadStubCompiler::CompileLoadCallback(String* name, 2364e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke JSObject* object, 2365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 2366e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AccessorInfo* callback) { 2367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2368402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 2369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 2370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Failure* failure = Failure::InternalError(); 23753bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch bool success = GenerateLoadCallback(object, holder, eax, ecx, ebx, edx, edi, 2376e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke callback, name, &miss, &failure); 2377e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!success) return failure; 2378e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* LoadStubCompiler::CompileLoadConstant(JSObject* object, 2388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 2389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* value, 2390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name) { 2391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2392402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 2393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 2394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch GenerateLoadConstant(object, holder, eax, ebx, edx, edi, value, name, &miss); 2399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CONSTANT_FUNCTION, name); 2404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, 2408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 2409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name) { 2410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2411402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 2412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 2413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupResult lookup; 2418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupPostInterceptor(holder, name, &lookup); 2419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // TODO(368): Compile in the whole chain: all the interceptors in 2421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // prototypes and ultimate answer. 2422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadInterceptor(receiver, 2423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block holder, 2424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &lookup, 2425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block eax, 2426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ecx, 2427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block edx, 2428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ebx, 24293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch edi, 2430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block name, 2431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &miss); 2432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* LoadStubCompiler::CompileLoadGlobal(JSObject* object, 2442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GlobalObject* holder, 2443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSGlobalPropertyCell* cell, 2444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name, 2445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_dont_delete) { 2446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2447402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : receiver 2448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ecx : name 2449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the object is the holder then we know that it's a global 2454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object which can only happen for contextual loads. In this case, 2455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the receiver cannot be a smi. 2456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object != holder) { 2457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(eax, Immediate(kSmiTagMask)); 2458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &miss, not_taken); 2459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 24623bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CheckPrototypes(object, eax, holder, ebx, edx, edi, name, &miss); 2463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the value from the cell. 2465402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); 2466402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); 2467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for deleted property if property can actually be deleted. 2469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!is_dont_delete) { 2470402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(ebx, Factory::the_hole_value()); 2471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &miss, not_taken); 2472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (FLAG_debug_code) { 2473402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(ebx, Factory::the_hole_value()); 2474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Check(not_equal, "DontDelete cells can't contain the hole"); 2475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::named_load_global_inline, 1); 2478402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(eax, ebx); 2479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 2480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::named_load_global_inline_miss, 1); 2483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(NORMAL, name); 2487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadField(String* name, 2491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* receiver, 2492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 2493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index) { 2494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2495402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 2496402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 2497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::keyed_load_field, 1); 2502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 2504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(Operand(eax), Immediate(Handle<String>(name))); 2505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss, not_taken); 2506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25073bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); 2508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ DecrementCounter(&Counters::keyed_load_field, 1); 2511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(FIELD, name); 2515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadCallback(String* name, 2519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* receiver, 2520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 2521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AccessorInfo* callback) { 2522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2523402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 2524402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 2525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::keyed_load_callback, 1); 2530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 2532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(Operand(eax), Immediate(Handle<String>(name))); 2533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss, not_taken); 2534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2535e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Failure* failure = Failure::InternalError(); 25363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch bool success = GenerateLoadCallback(receiver, holder, edx, eax, ebx, ecx, edi, 2537e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke callback, name, &miss, &failure); 2538e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!success) return failure; 2539e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ DecrementCounter(&Counters::keyed_load_callback, 1); 2542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadConstant(String* name, 2550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* receiver, 2551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 2552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* value) { 2553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2554402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 2555402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 2556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::keyed_load_constant_function, 1); 2561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 2563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(Operand(eax), Immediate(Handle<String>(name))); 2564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss, not_taken); 2565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch GenerateLoadConstant(receiver, holder, edx, ebx, ecx, edi, 2567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value, name, &miss); 2568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ DecrementCounter(&Counters::keyed_load_constant_function, 1); 2570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CONSTANT_FUNCTION, name); 2574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, 2578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 2579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name) { 2580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2581402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 2582402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 2583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::keyed_load_interceptor, 1); 2588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 2590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(Operand(eax), Immediate(Handle<String>(name))); 2591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss, not_taken); 2592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupResult lookup; 2594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupPostInterceptor(holder, name, &lookup); 2595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadInterceptor(receiver, 2596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block holder, 2597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &lookup, 2598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block edx, 2599402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu eax, 2600402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ecx, 2601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ebx, 26023bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch edi, 2603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block name, 2604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &miss); 2605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ DecrementCounter(&Counters::keyed_load_interceptor, 1); 2607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) { 2617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2618402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 2619402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 2620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::keyed_load_array_length, 1); 2625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 2627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(Operand(eax), Immediate(Handle<String>(name))); 2628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss, not_taken); 2629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2630402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateLoadArrayLength(masm(), edx, ecx, &miss); 2631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ DecrementCounter(&Counters::keyed_load_array_length, 1); 2633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { 2641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2642402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 2643402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 2644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::keyed_load_string_length, 1); 2649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 2651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(Operand(eax), Immediate(Handle<String>(name))); 2652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss, not_taken); 2653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2654402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss); 2655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ DecrementCounter(&Counters::keyed_load_string_length, 1); 2657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { 2665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2666402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- eax : key 2667402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- edx : receiver 2668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::keyed_load_function_prototype, 1); 2673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 2675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(Operand(eax), Immediate(Handle<String>(name))); 2676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss, not_taken); 2677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2678402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); 2679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ DecrementCounter(&Counters::keyed_load_function_prototype, 1); 2681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Specialized stub for constructing objects from functions which only have only 2689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// simple assignments of the form this.x = ...; in their body. 2690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* ConstructStubCompiler::CompileConstructStub( 2691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SharedFunctionInfo* shared) { 2692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : argc 2694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- edi : constructor 2695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 2696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[4] : last argument 2697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label generic_stub_call; 2699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 2700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check to see whether there are any break points in the function code. If 2701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // there are jump to the generic constructor stub which calls the actual 2702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // code for the function thereby hitting the break points. 2703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 2704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kDebugInfoOffset)); 2705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(ebx, Factory::undefined_value()); 2706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &generic_stub_call, not_taken); 2707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 2708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the initial map and verify that it is in fact a map. 2710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); 2711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Will both indicate a NULL and a Smi. 2712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(ebx, Immediate(kSmiTagMask)); 2713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(zero, &generic_stub_call); 2714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpObjectType(ebx, MAP_TYPE, ecx); 2715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &generic_stub_call); 2716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 2718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cannot construct functions this way. 2719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edi: constructor 2720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ebx: initial map 2721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpInstanceType(ebx, JS_FUNCTION_TYPE); 2722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Assert(not_equal, "Function constructed by construct stub."); 2723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 2724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Now allocate the JSObject on the heap by moving the new space allocation 2726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // top forward. 2727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edi: constructor 2728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ebx: initial map 2729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset)); 2730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ shl(ecx, kPointerSizeLog2); 2731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ AllocateInNewSpace(ecx, 2732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block edx, 2733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ecx, 2734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block no_reg, 2735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &generic_stub_call, 2736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NO_ALLOCATION_FLAGS); 2737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocated the JSObject, now initialize the fields and add the heap tag. 2739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ebx: initial map 2740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edx: JSObject (untagged) 2741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(edx, JSObject::kMapOffset), ebx); 2742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, Factory::empty_fixed_array()); 2743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(edx, JSObject::kPropertiesOffset), ebx); 2744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(edx, JSObject::kElementsOffset), ebx); 2745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push the allocated object to the stack. This is the object that will be 2747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // returned (after it is tagged). 2748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(edx); 2749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: argc 2751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edx: JSObject (untagged) 2752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the address of the first in-object property into edx. 2753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(edx, Operand(edx, JSObject::kHeaderSize)); 2754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the location of the first argument. The stack contains the 2755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // allocated object and the return address on top of the argc arguments. 2756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(ecx, Operand(esp, eax, times_4, 1 * kPointerSize)); 2757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use edi for holding undefined which is used in several places below. 2759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edi, Factory::undefined_value()); 2760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // eax: argc 2762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ecx: first argument 2763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edx: first in-object property of the JSObject 2764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // edi: undefined 2765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the initialized properties with a constant value or a passed argument 2766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // depending on the this.x = ...; assignment in the function. 2767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < shared->this_property_assignments_count(); i++) { 2768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (shared->IsThisPropertyAssignmentArgument(i)) { 2769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the argument assigned to the property is actually passed. 2770e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // If argument is not passed the property is set to undefined, 2771e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // otherwise find it on the stack. 2772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int arg_number = shared->GetThisPropertyAssignmentArgument(i); 2773e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(ebx, edi); 2774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, arg_number); 2775e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (CpuFeatures::IsSupported(CMOV)) { 2776e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke CpuFeatures::Scope use_cmov(CMOV); 2777e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmov(above, ebx, Operand(ecx, arg_number * -kPointerSize)); 2778e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 2779e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label not_passed; 2780e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(below_equal, ¬_passed); 2781e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(ebx, Operand(ecx, arg_number * -kPointerSize)); 2782e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(¬_passed); 2783e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2784e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store value in the property. 2785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(edx, i * kPointerSize), ebx); 2786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 2787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the property to the constant value. 2788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i)); 2789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(edx, i * kPointerSize), Immediate(constant)); 2790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the unused in-object property fields with undefined. 2794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = shared->this_property_assignments_count(); 2795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i < shared->CalculateInObjectProperties(); 2796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i++) { 2797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(edx, i * kPointerSize), edi); 2798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move argc to ebx and retrieve and tag the JSObject to return. 2801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, eax); 2802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(eax); 2803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ or_(Operand(eax), Immediate(kHeapObjectTag)); 2804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Remove caller arguments and receiver from the stack and return. 2806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ecx); 2807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(esp, Operand(esp, ebx, times_pointer_size, 1 * kPointerSize)); 2808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); 2809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::constructed_objects, 1); 2810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::constructed_objects_stub, 1); 2811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 2812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the generic stub in case the specialized code cannot handle the 2814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // construction. 2815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&generic_stub_call); 2816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric); 2817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> generic_construct_stub(code); 2818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); 2819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(); 2822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 2826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 2828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_IA32 2830