stub-cache-arm.cc revision 8a31eba00023874d4a1dcdc5f411cc4336776874
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_ARM) 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, 463e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu Register offset, 473e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu Register scratch, 483e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu Register scratch2) { 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference key_offset(SCTableReference::keyReference(table)); 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference value_offset(SCTableReference::valueReference(table)); 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 523e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu uint32_t key_off_addr = reinterpret_cast<uint32_t>(key_offset.address()); 533e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu uint32_t value_off_addr = reinterpret_cast<uint32_t>(value_offset.address()); 543e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 553e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Check the relative positions of the address fields. 563e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(value_off_addr > key_off_addr); 573e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT((value_off_addr - key_off_addr) % 4 == 0); 583e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT((value_off_addr - key_off_addr) < (256 * 4)); 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 603e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu Label miss; 613e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu Register offsets_base_addr = scratch; 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the key in the entry matches the name. 643e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ mov(offsets_base_addr, Operand(key_offset)); 653e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ ldr(ip, MemOperand(offsets_base_addr, offset, LSL, 1)); 666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(name, ip); 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the code entry from the cache. 703e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ add(offsets_base_addr, offsets_base_addr, 713e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu Operand(value_off_addr - key_off_addr)); 723e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ ldr(scratch2, MemOperand(offsets_base_addr, offset, LSL, 1)); 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the flags match what we're looking for. 753e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ ldr(scratch2, FieldMemOperand(scratch2, Code::kFlagsOffset)); 763e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ bic(scratch2, scratch2, Operand(Code::kFlagsNotUsedInLookup)); 773e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ cmp(scratch2, Operand(flags)); 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 803e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Re-load code entry from cache. 813e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ ldr(offset, MemOperand(offsets_base_addr, offset, LSL, 1)); 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the first instruction in the code stub. 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(offset, offset, Operand(Code::kHeaderSize - kHeapObjectTag)); 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(offset); 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 873e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Miss: fall through. 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 923bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// Helper function used to check that the dictionary doesn't contain 933bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// the property. This function may return false negatives, so miss_label 943bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// must always call a backup property check that is complete. 953bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// This function is safe to call if the receiver has fast properties. 963bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// Name must be a symbol and receiver must be a heap object. 973bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochstatic void GenerateDictionaryNegativeLookup(MacroAssembler* masm, 983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* miss_label, 993bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register receiver, 1003bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch String* name, 1013bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch0, 1023bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch1) { 1033bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(name->IsSymbol()); 1043bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ IncrementCounter(&Counters::negative_lookups, 1, scratch0, scratch1); 1053bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ IncrementCounter(&Counters::negative_lookups_miss, 1, scratch0, scratch1); 1063bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1073bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label done; 1083bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1093bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const int kInterceptorOrAccessCheckNeededMask = 1103bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); 1113bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1123bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Bail out if the receiver has a named interceptor or requires access checks. 1133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register map = scratch1; 1143bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); 1153bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ ldrb(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); 1163bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ tst(scratch0, Operand(kInterceptorOrAccessCheckNeededMask)); 1173bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ b(ne, miss_label); 1183bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1193bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Check that receiver is a JSObject. 1203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ ldrb(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); 1213bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ cmp(scratch0, Operand(FIRST_JS_OBJECT_TYPE)); 1223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ b(lt, miss_label); 1233bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1243bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Load properties array. 1253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register properties = scratch0; 1263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 1273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Check that the properties array is a dictionary. 1283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ ldr(map, FieldMemOperand(properties, HeapObject::kMapOffset)); 1293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register tmp = properties; 1303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); 1313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ cmp(map, tmp); 1323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ b(ne, miss_label); 1333bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Restore the temporarily used register. 1353bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 1363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Compute the capacity mask. 1383bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const int kCapacityOffset = 1393bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch StringDictionary::kHeaderSize + 1403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch StringDictionary::kCapacityIndex * kPointerSize; 1413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1423bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Generate an unrolled loop that performs a few probes before 1433bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // giving up. 1443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch static const int kProbes = 4; 1453bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const int kElementsStartOffset = 1463bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch StringDictionary::kHeaderSize + 1473bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch StringDictionary::kElementsStartIndex * kPointerSize; 1483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1493bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // If names of slots in range from 1 to kProbes - 1 for the hash value are 1503bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // not equal to the name and kProbes-th slot is not used (its name is the 1513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // undefined value), it guarantees the hash table doesn't contain the 1523bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // property. It's true even if some slots represent deleted properties 1533bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // (their names are the null value). 1543bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch for (int i = 0; i < kProbes; i++) { 1553bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // scratch0 points to properties hash. 1563bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Compute the masked index: (hash + i + i * i) & mask. 1573bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register index = scratch1; 1583bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Capacity is smi 2^n. 1593bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ ldr(index, FieldMemOperand(properties, kCapacityOffset)); 1603bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ sub(index, index, Operand(1)); 1613bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ and_(index, index, Operand( 1623bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Smi::FromInt(name->Hash() + StringDictionary::GetProbeOffset(i)))); 1633bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Scale the index by multiplying by the entry size. 1653bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(StringDictionary::kEntrySize == 3); 1663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ add(index, index, Operand(index, LSL, 1)); // index *= 3. 1673bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1683bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register entity_name = scratch1; 1693bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Having undefined at this place means the name is not contained. 1703bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT_EQ(kSmiTagSize, 1); 1713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register tmp = properties; 1723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ add(tmp, properties, Operand(index, LSL, 1)); 1733bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ ldr(entity_name, FieldMemOperand(tmp, kElementsStartOffset)); 1743bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1753bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(!tmp.is(entity_name)); 1763bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ LoadRoot(tmp, Heap::kUndefinedValueRootIndex); 1773bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ cmp(entity_name, tmp); 1783bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch if (i != kProbes - 1) { 1793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ b(eq, &done); 1803bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1813bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Stop if found the property. 1823bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ cmp(entity_name, Operand(Handle<String>(name))); 1833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ b(eq, miss_label); 1843bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1853bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Check if the entry name is not a symbol. 1863bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ ldr(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset)); 1873bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ ldrb(entity_name, 1883bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch FieldMemOperand(entity_name, Map::kInstanceTypeOffset)); 1893bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ tst(entity_name, Operand(kIsSymbolMask)); 1903bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ b(eq, miss_label); 1913bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1923bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Restore the properties. 1933bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ ldr(properties, 1943bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 1953bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } else { 1963bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Give up probing if still not found the undefined value. 1973bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ b(ne, miss_label); 1983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 1993bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 2003bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ bind(&done); 2013bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ DecrementCounter(&Counters::negative_lookups_miss, 1, scratch0, scratch1); 2023bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch} 2033bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 2043bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCache::GenerateProbe(MacroAssembler* masm, 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Flags flags, 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register name, 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 2103e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu Register extra, 2113e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu Register extra2) { 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure that code is valid. The shifting code relies on the 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // entry size being 8. 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(sizeof(Entry) == 8); 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure the flags does not name a specific type. 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(Code::ExtractTypeFromFlags(flags) == 0); 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure that there are no register conflicts. 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!scratch.is(receiver)); 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!scratch.is(name)); 2243e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(!extra.is(receiver)); 2253e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(!extra.is(name)); 2263e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(!extra.is(scratch)); 2273e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(!extra2.is(receiver)); 2283e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(!extra2.is(name)); 2293e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(!extra2.is(scratch)); 2303e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(!extra2.is(extra)); 2313e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 2323e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Check scratch, extra and extra2 registers are valid. 2333e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(!scratch.is(no_reg)); 2343e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(!extra.is(no_reg)); 2353e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(!extra2.is(no_reg)); 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(receiver, Operand(kSmiTagMask)); 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &miss); 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the map of the receiver and compute the hash. 242d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(scratch, FieldMemOperand(name, String::kHashFieldOffset)); 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(ip, FieldMemOperand(receiver, HeapObject::kMapOffset)); 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(scratch, scratch, Operand(ip)); 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ eor(scratch, scratch, Operand(flags)); 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(scratch, 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block scratch, 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand((kPrimaryTableSize - 1) << kHeapObjectTagSize)); 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the primary table. 2513e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ProbeTable(masm, flags, kPrimary, name, scratch, extra, extra2); 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Primary miss: Compute hash for secondary probe. 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(scratch, scratch, Operand(name)); 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(scratch, scratch, Operand(flags)); 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(scratch, 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block scratch, 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand((kSecondaryTableSize - 1) << kHeapObjectTagSize)); 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the secondary table. 2613e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ProbeTable(masm, flags, kSecondary, name, scratch, extra, extra2); 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cache miss: Fall-through and let caller handle the miss by 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // entering the runtime system. 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index, 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register prototype) { 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the global or builtins object from the current context. 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the global context from the global or builtins object. 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(prototype, 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldMemOperand(prototype, GlobalObject::kGlobalContextOffset)); 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the function from the global context. 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(prototype, MemOperand(prototype, Context::SlotOffset(index))); 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the initial map. The global functions all have initial maps. 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(prototype, 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldMemOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset)); 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the prototype from the initial map. 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( 2880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen MacroAssembler* masm, int index, Register prototype, Label* miss) { 2890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Check we're still in the same context. 2900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ ldr(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); 2910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Move(ip, Top::global()); 2920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ cmp(prototype, ip); 2930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ b(ne, miss); 2947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Get the global function with the given index. 2957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch JSFunction* function = JSFunction::cast(Top::global_context()->get(index)); 2967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Load its initial map. The global functions all have initial maps. 2977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Move(prototype, Handle<Map>(function->initial_map())); 2987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Load the prototype from the initial map. 2997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); 3007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 3017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 3027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Load a fast property out of a holder object (src). In-object properties 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// are loaded directly otherwise the property is loaded from the properties 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// fixed array. 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register dst, Register src, 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, int index) { 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust for the number of properties stored in the holder. 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block index -= holder->map()->inobject_properties(); 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (index < 0) { 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the property straight out of the holder. 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = holder->map()->instance_size() + (index * kPointerSize); 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(dst, FieldMemOperand(src, offset)); 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the offset into the properties array. 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = index * kPointerSize + FixedArray::kHeaderSize; 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(dst, FieldMemOperand(src, JSObject::kPropertiesOffset)); 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(dst, FieldMemOperand(dst, offset)); 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss_label) { 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(receiver, Operand(kSmiTagMask)); 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, miss_label); 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is a JS array. 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE); 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, miss_label); 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load length directly from the JS array. 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Ret(); 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 342402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// Generate code to check if an object is a string. If the object is a 343402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// heap object, its map's instance type is left in the scratch1 register. 344402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// If this is not needed, scratch1 and scratch2 may be the same register. 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GenerateStringCheck(MacroAssembler* masm, 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* smi, 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* non_string_object) { 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(receiver, Operand(kSmiTagMask)); 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, smi); 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is a string. 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset)); 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(scratch2, scratch1, Operand(kIsNotStringMask)); 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The cast is to resolve the overload for the argument of 0x0. 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag))); 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, non_string_object); 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate code to load the length from a string object and return the length. 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// If the receiver object is not a string or a wrapped string object the 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// execution continues at the miss label. The register containing the 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// receiver is potentially clobbered. 369402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, 370402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register receiver, 371402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register scratch1, 372402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register scratch2, 373402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label* miss) { 374402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label check_wrapper; 375402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the object is a string leaving the instance type in the 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch1 register. 378402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateStringCheck(masm, receiver, scratch1, scratch2, miss, &check_wrapper); 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load length directly from the string. 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, FieldMemOperand(receiver, String::kLengthOffset)); 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Ret(); 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the object is a JSValue wrapper. 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&check_wrapper); 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(scratch1, Operand(JS_VALUE_TYPE)); 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, miss); 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 389402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Unwrap the value and check if the wrapped value is a string. 390402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ldr(scratch1, FieldMemOperand(receiver, JSValue::kValueOffset)); 391402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu GenerateStringCheck(masm, scratch1, scratch2, scratch2, miss, miss); 392402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ldr(r0, FieldMemOperand(scratch1, String::kLengthOffset)); 393402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ Ret(); 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss_label) { 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, scratch1); 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Ret(); 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate StoreField code, value is passed in r0 register. 409402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// When leaving generated code after success, the receiver_reg and name_reg 410402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// may be clobbered. Upon branch to miss_label, the receiver and name 411402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// registers have their original values. 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateStoreField(MacroAssembler* masm, 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* object, 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index, 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Map* transition, 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver_reg, 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register name_reg, 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss_label) { 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0 : value 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label exit; 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(receiver_reg, Operand(kSmiTagMask)); 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, miss_label); 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the receiver hasn't changed. 428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(scratch, Operand(Handle<Map>(object->map()))); 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, miss_label); 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform global security token check if needed. 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsJSGlobalProxy()) { 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stub never generated for non-global objects that require access 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks. 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform map transition for the receiver if necessary. 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) { 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The properties must be extended before we can store the value. 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We jump to a runtime call that extends the properties array. 445402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(receiver_reg); 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, Operand(Handle<Map>(transition))); 4476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Push(r2, r0); 4486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference( 449402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage)), 450402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 3, 1); 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (transition != NULL) { 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update the map of the object; no write barrier updating is 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // needed because the map is never in new space. 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ip, Operand(Handle<Map>(transition))); 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(ip, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust for the number of properties stored in the object. Even in the 462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // face of a transition we can use the old map here because the size of the 463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object and the number of in-object properties is not going to change. 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block index -= object->map()->inobject_properties(); 465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (index < 0) { 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the property straight into the object. 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = object->map()->instance_size() + (index * kPointerSize); 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r0, FieldMemOperand(receiver_reg, offset)); 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Skip updating write barrier if storing a smi. 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r0, Operand(kSmiTagMask)); 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &exit); 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update the write barrier for the array address. 4769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Pass the now unused name_reg as a scratch register. 4779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ RecordWrite(receiver_reg, Operand(offset), name_reg, scratch); 478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Write to the properties array. 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = index * kPointerSize + FixedArray::kHeaderSize; 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the properties array 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(scratch, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r0, FieldMemOperand(scratch, offset)); 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Skip updating write barrier if storing a smi. 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r0, Operand(kSmiTagMask)); 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &exit); 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update the write barrier for the array address. 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Ok to clobber receiver_reg and name_reg, since we return. 4919dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ RecordWrite(scratch, Operand(offset), name_reg, receiver_reg); 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the value (register r0). 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&exit); 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Ret(); 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code* code = NULL; 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (kind == Code::LOAD_IC) { 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block code = Builtins::builtin(Builtins::LoadIC_Miss); 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block code = Builtins::builtin(Builtins::KeyedLoadIC_Miss); 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> ic(code); 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkestatic void GenerateCallFunction(MacroAssembler* masm, 5154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Object* object, 5164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke const ParameterCount& arguments, 5174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Label* miss) { 5184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // ----------- S t a t e ------------- 5194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- r0: receiver 5204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- r1: function to call 5214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // ----------------------------------- 5224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 5234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Check that the function really is a function. 5244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ BranchOnSmi(r1, miss); 525402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); 5264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ b(ne, miss); 5274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 5284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Patch the receiver on the stack with the global proxy if 5294515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // necessary. 5304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (object->IsGlobalObject()) { 5314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); 5324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ str(r3, MemOperand(sp, arguments.immediate() * kPointerSize)); 5334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 5344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 5354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Invoke the function. 5364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ InvokeFunction(r1, arguments, JUMP_FUNCTION); 5374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke} 5384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 5394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 5404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkestatic void PushInterceptorArguments(MacroAssembler* masm, 5414515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Register receiver, 5424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Register holder, 5434515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Register name, 5444515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke JSObject* holder_obj) { 5454515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(name); 5464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); 5474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ASSERT(!Heap::InNewSpace(interceptor)); 5486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch = name; 5494515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mov(scratch, Operand(Handle<Object>(interceptor))); 5504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(scratch); 5516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(receiver); 5526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(holder); 5534515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ ldr(scratch, FieldMemOperand(scratch, InterceptorInfo::kDataOffset)); 5544515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(scratch); 5554515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke} 5564515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 5574515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 5584515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkestatic void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, 5594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Register receiver, 5604515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Register holder, 5614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Register name, 5624515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke JSObject* holder_obj) { 5634515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke PushInterceptorArguments(masm, receiver, holder, name, holder_obj); 5644515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 5654515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ExternalReference ref = 5664515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly)); 5674515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mov(r0, Operand(5)); 5684515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mov(r1, Operand(ref)); 5694515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 5704515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke CEntryStub stub(1); 5714515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallStub(&stub); 5724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke} 5734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 5744515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 5756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Reserves space for the extra arguments to FastHandleApiCall in the 5766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// caller's frame. 5776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// 5786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// These arguments are set by CheckPrototypes and GenerateFastApiCall. 5796ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void ReserveSpaceForFastApiCall(MacroAssembler* masm, 5806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch) { 5816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(scratch, Operand(Smi::FromInt(0))); 5826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(scratch); 5836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(scratch); 5846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(scratch); 5856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(scratch); 5866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 5876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Undoes the effects of ReserveSpaceForFastApiCall. 5906ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void FreeSpaceForFastApiCall(MacroAssembler* masm) { 5916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Drop(4); 5926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 5936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Generates call to FastHandleApiCall builtin. 5966ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void GenerateFastApiCall(MacroAssembler* masm, 5976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const CallOptimization& optimization, 5986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int argc) { 5996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the function and setup the context. 6006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSFunction* function = optimization.constant_function(); 6018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(r5, Operand(Handle<JSFunction>(function))); 6028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(cp, FieldMemOperand(r5, JSFunction::kContextOffset)); 6036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Pass the additional arguments FastHandleApiCall expects. 6056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bool info_loaded = false; 6066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Object* callback = optimization.api_call_info()->callback(); 6076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (Heap::InNewSpace(callback)) { 6086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block info_loaded = true; 6096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Move(r0, Handle<CallHandlerInfo>(optimization.api_call_info())); 6108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r7, FieldMemOperand(r0, CallHandlerInfo::kCallbackOffset)); 6116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 6128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Move(r7, Handle<Object>(callback)); 6136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 6146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Object* call_data = optimization.api_call_info()->data(); 6156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (Heap::InNewSpace(call_data)) { 6166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (!info_loaded) { 6176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Move(r0, Handle<CallHandlerInfo>(optimization.api_call_info())); 6186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 6198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r6, FieldMemOperand(r0, CallHandlerInfo::kDataOffset)); 6206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 6218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Move(r6, Handle<Object>(call_data)); 6226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 6236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ add(sp, sp, Operand(1 * kPointerSize)); 6256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ stm(ia, sp, r5.bit() | r6.bit() | r7.bit()); 6266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ sub(sp, sp, Operand(1 * kPointerSize)); 6276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Set the number of arguments. 6296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r0, Operand(argc + 4)); 6306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Jump to the fast api call builtin (tail call). 6326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Code> code = Handle<Code>( 6336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Builtins::builtin(Builtins::FastHandleApiCall)); 6346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ParameterCount expected(0); 6356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ InvokeCode(code, expected, expected, 6366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block RelocInfo::CODE_TARGET, JUMP_FUNCTION); 6376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 6386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6406ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass CallInterceptorCompiler BASE_EMBEDDED { 6416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public: 6426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CallInterceptorCompiler(StubCompiler* stub_compiler, 6436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const ParameterCount& arguments, 6446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register name) 6456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block : stub_compiler_(stub_compiler), 6466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block arguments_(arguments), 6476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block name_(name) {} 6486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void Compile(MacroAssembler* masm, 6506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSObject* object, 6516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSObject* holder, 6526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block String* name, 6536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block LookupResult* lookup, 6546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register receiver, 6556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch1, 6566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch2, 6573bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 6586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* miss) { 6596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(holder->HasNamedInterceptor()); 6606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); 6616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the receiver isn't a smi. 6636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ BranchOnSmi(receiver, miss); 6646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CallOptimization optimization(lookup); 6666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (optimization.is_constant_call()) { 6686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CompileCacheable(masm, 6696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block object, 6706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block receiver, 6716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block scratch1, 6726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block scratch2, 6733bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch3, 6746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block holder, 6756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block lookup, 6766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block name, 6776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block optimization, 6786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block miss); 6796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 6806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CompileRegular(masm, 6816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block object, 6826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block receiver, 6836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block scratch1, 6846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block scratch2, 6853bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch3, 6866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block name, 6876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block holder, 6886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block miss); 6896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 6906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 6916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private: 6936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void CompileCacheable(MacroAssembler* masm, 6946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSObject* object, 6956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register receiver, 6966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch1, 6976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch2, 6983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke JSObject* interceptor_holder, 7006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block LookupResult* lookup, 7016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block String* name, 7026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const CallOptimization& optimization, 7036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* miss_label) { 7046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(optimization.is_constant_call()); 7056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(!lookup->holder()->IsGlobalObject()); 7066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 7076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int depth1 = kInvalidProtoDepth; 7086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int depth2 = kInvalidProtoDepth; 7096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bool can_do_fast_api_call = false; 7106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (optimization.is_simple_api_call() && 7116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block !lookup->holder()->IsGlobalObject()) { 712f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke depth1 = 713f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke optimization.GetPrototypeDepthOfExpectedType(object, 714f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke interceptor_holder); 7156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (depth1 == kInvalidProtoDepth) { 716f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke depth2 = 717f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke optimization.GetPrototypeDepthOfExpectedType(interceptor_holder, 718f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke lookup->holder()); 7196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 7206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block can_do_fast_api_call = (depth1 != kInvalidProtoDepth) || 7216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block (depth2 != kInvalidProtoDepth); 7226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 7236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 7246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ IncrementCounter(&Counters::call_const_interceptor, 1, 7256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block scratch1, scratch2); 7266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 7276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (can_do_fast_api_call) { 7286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ IncrementCounter(&Counters::call_const_interceptor_fast_api, 1, 7296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block scratch1, scratch2); 7306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ReserveSpaceForFastApiCall(masm, scratch1); 7316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 7326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 733f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check that the maps from receiver to interceptor's holder 734f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // haven't changed and thus we can invoke interceptor. 7356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss_cleanup; 7366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; 7376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register holder = 7387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch stub_compiler_->CheckPrototypes(object, receiver, 7397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch interceptor_holder, scratch1, 7403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch2, scratch3, name, depth1, miss); 7416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 742f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invoke an interceptor and if it provides a value, 743f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // branch to |regular_invoke|. 7446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label regular_invoke; 745f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2, 7466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ®ular_invoke); 7476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 748f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Interceptor returned nothing for this property. Try to use cached 749f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // constant function. 7506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 751f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check that the maps from interceptor's holder to constant function's 752f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // holder haven't changed and thus we can use cached constant function. 7537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (interceptor_holder != lookup->holder()) { 7547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch stub_compiler_->CheckPrototypes(interceptor_holder, receiver, 7557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch lookup->holder(), scratch1, 7563bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch2, scratch3, name, depth2, miss); 7577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 7587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // CheckPrototypes has a side effect of fetching a 'holder' 7597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // for API (object which is instanceof for the signature). It's 7607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // safe to omit it here, as if present, it should be fetched 7617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // by the previous CheckPrototypes. 7627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(depth2 == kInvalidProtoDepth); 7637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 7646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 765f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invoke function. 7666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (can_do_fast_api_call) { 7676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GenerateFastApiCall(masm, optimization, arguments_.immediate()); 7686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 7696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ InvokeFunction(optimization.constant_function(), arguments_, 7706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JUMP_FUNCTION); 7716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 7726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 773f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Deferred code for fast API call case---clean preallocated space. 7746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (can_do_fast_api_call) { 7756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss_cleanup); 7766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FreeSpaceForFastApiCall(masm); 7776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ b(miss_label); 7786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 7796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invoke a regular function. 7816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(®ular_invoke); 7826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (can_do_fast_api_call) { 7836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FreeSpaceForFastApiCall(masm); 7846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 7856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 7866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 7876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void CompileRegular(MacroAssembler* masm, 7886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSObject* object, 7896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register receiver, 7906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch1, 7916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch2, 7923bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 7936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block String* name, 794f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke JSObject* interceptor_holder, 7956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* miss_label) { 7966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register holder = 797f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, 7983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch1, scratch2, scratch3, name, 7996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block miss_label); 8006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Call a runtime function to load the interceptor property. 8026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ EnterInternalFrame(); 8036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Save the name_ register across the call. 8046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(name_); 8056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block PushInterceptorArguments(masm, 8076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block receiver, 8086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block holder, 8096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block name_, 810f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke interceptor_holder); 8116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CallExternalReference( 8136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ExternalReference( 8146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block IC_Utility(IC::kLoadPropertyWithInterceptorForCall)), 8156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5); 8166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Restore the name_ register. 8186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(name_); 8196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ LeaveInternalFrame(); 8206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 8216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void LoadWithInterceptor(MacroAssembler* masm, 8236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register receiver, 8246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register holder, 8256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSObject* holder_obj, 8266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch, 8276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* interceptor_succeeded) { 8286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ EnterInternalFrame(); 8296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Push(holder, name_); 8306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CompileCallLoadPropertyWithInterceptor(masm, 8326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block receiver, 8336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block holder, 8346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block name_, 8356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block holder_obj); 8366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(name_); // Restore the name. 8386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(receiver); // Restore the holder. 8396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ LeaveInternalFrame(); 8406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // If interceptor returns no-result sentinel, call the constant function. 8426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); 8436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(r0, scratch); 8446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ b(ne, interceptor_succeeded); 8456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 8466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block StubCompiler* stub_compiler_; 8486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const ParameterCount& arguments_; 8496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register name_; 8506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}; 8516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Generate code to check that a global property cell is empty. Create 8546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// the property cell at compilation time if no cell exists for the 8556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// property. 8565913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCell( 8575913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck MacroAssembler* masm, 8585913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck GlobalObject* global, 8595913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck String* name, 8605913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Register scratch, 8615913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Label* miss) { 8625913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* probe; 8635913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck { MaybeObject* maybe_probe = global->EnsurePropertyCell(name); 8645913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_probe->ToObject(&probe)) return maybe_probe; 8655913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 8666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); 8676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(cell->value()->IsTheHole()); 8686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(scratch, Operand(Handle<Object>(cell))); 8696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ldr(scratch, 8706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); 8716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 8726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(scratch, ip); 8736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ b(ne, miss); 8746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return cell; 8756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 8766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm()) 880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegister StubCompiler::CheckPrototypes(JSObject* object, 883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register object_reg, 884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register holder_reg, 8863bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch1, 8873bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch2, 888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name, 889402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int save_at_depth, 8903bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* miss) { 8913bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Make sure there's no overlap between holder and object registers. 8923bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 8933bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) 8943bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch && !scratch2.is(scratch1)); 8953bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 8963bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Keep track of the current object in register reg. 8973bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register reg = object_reg; 8983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch int depth = 0; 8993bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 9003bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch if (save_at_depth == depth) { 9013bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ str(reg, MemOperand(sp)); 9023bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 9033bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 9043bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Check the maps in the prototype chain. 9053bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Traverse the prototype chain from the object and do map checks. 9063bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch JSObject* current = object; 9073bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch while (current != holder) { 9083bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch depth++; 9093bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 9103bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Only global objects and objects that do not require access 9113bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // checks are allowed in stubs. 9123bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); 9133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 9143bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch JSObject* prototype = JSObject::cast(current->GetPrototype()); 9153bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch if (!current->HasFastProperties() && 9163bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch !current->IsJSGlobalObject() && 9173bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch !current->IsJSGlobalProxy()) { 9183bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch if (!name->IsSymbol()) { 9195913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck MaybeObject* lookup_result = Heap::LookupSymbol(name); 9203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch if (lookup_result->IsFailure()) { 9213bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch set_failure(Failure::cast(lookup_result)); 9223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch return reg; 9233bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } else { 9245913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck name = String::cast(lookup_result->ToObjectUnchecked()); 9253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 9263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 9273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(current->property_dictionary()->FindEntry(name) == 9283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch StringDictionary::kNotFound); 9293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 9303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch GenerateDictionaryNegativeLookup(masm(), 9313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch miss, 9323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch reg, 9333bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch name, 9343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch1, 9353bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch2); 9363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); 9373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch reg = holder_reg; // from now the object is in holder_reg 9383bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); 9393bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } else { 9403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Get the map of the current object. 9413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); 9423bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ cmp(scratch1, Operand(Handle<Map>(current->map()))); 9433bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 9443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Branch on the result of the map check. 9453bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ b(ne, miss); 9463bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 9473bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Check access rights to the global object. This has to happen 9483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // after the map check so that we know that the object is 9493bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // actually a global object. 9503bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch if (current->IsJSGlobalProxy()) { 9513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ CheckAccessGlobalProxy(reg, scratch1, miss); 9523bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Restore scratch register to be the map of the object. In the 9533bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // new space case below, we load the prototype from the map in 9543bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // the scratch register. 9553bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); 9563bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 9573bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 9583bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch reg = holder_reg; // from now the object is in holder_reg 9593bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch if (Heap::InNewSpace(prototype)) { 9603bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // The prototype is in new space; we cannot store a reference 9613bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // to it in the code. Load it from the map. 9623bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); 9633bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } else { 9643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // The prototype is in old space; load it directly. 9653bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ mov(reg, Operand(Handle<JSObject>(prototype))); 9663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 9673bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 9683bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 9693bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch if (save_at_depth == depth) { 9703bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ str(reg, MemOperand(sp)); 9713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 9723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 9733bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Go to the next object in the prototype chain. 9743bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch current = prototype; 9753bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 9763bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 9773bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Check the holder map. 9783bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); 9793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ cmp(scratch1, Operand(Handle<Map>(current->map()))); 9803bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ b(ne, miss); 9813bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 9823bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Log the check depth. 9833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch LOG(IntEvent("check-maps-depth", depth + 1)); 9843bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 9853bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Perform security check for access to the global object and return 9863bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // the holder register. 9873bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(current == holder); 9883bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); 9893bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch if (current->IsJSGlobalProxy()) { 9903bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ CheckAccessGlobalProxy(reg, scratch1, miss); 9913bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If we've skipped any global objects, it's not enough to verify 9946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // that their maps haven't changed. We also need to check that the 9956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // property cell for the property is still empty. 9963bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch current = object; 9973bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch while (current != holder) { 9983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch if (current->IsGlobalObject()) { 9995913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck MaybeObject* cell = GenerateCheckPropertyCell(masm(), 10005913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck GlobalObject::cast(current), 10015913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck name, 10025913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck scratch1, 10035913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck miss); 10046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (cell->IsFailure()) { 10056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block set_failure(Failure::cast(cell)); 10063bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch return reg; 1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 10093bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch current = JSObject::cast(current->GetPrototype()); 1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1012402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Return the register containing the holder. 10133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch return reg; 1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadField(JSObject* object, 1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 10223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index, 1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name, 1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(receiver, Operand(kSmiTagMask)); 1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, miss); 1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register reg = 10323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, 10333bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch name, miss); 1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateFastPropertyLoad(masm(), r0, reg, holder, index); 1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Ret(); 1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadConstant(JSObject* object, 1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 10443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* value, 1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name, 1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(receiver, Operand(kSmiTagMask)); 1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, miss); 1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register reg = 10543bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CheckPrototypes(object, receiver, holder, 10553bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch1, scratch2, scratch3, name, miss); 1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the constant value. 1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, Operand(Handle<Object>(value))); 1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Ret(); 1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1063e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkebool StubCompiler::GenerateLoadCallback(JSObject* object, 1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObject* holder, 1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register name_reg, 1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 10693bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AccessorInfo* callback, 1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name, 1072e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label* miss, 1073e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Failure** failure) { 1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(receiver, Operand(kSmiTagMask)); 1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, miss); 1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register reg = 10803bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, 10813bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch name, miss); 1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push the arguments on the JS stack of the caller. 10846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(receiver); // Receiver. 10858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(scratch3, Operand(Handle<AccessorInfo>(callback))); // callback data 10868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(ip, FieldMemOperand(scratch3, AccessorInfo::kDataOffset)); 10878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Push(reg, ip, scratch3, name_reg); 1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to the runtime system. 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference load_callback_property = 1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference(IC_Utility(IC::kLoadCallbackProperty)); 10926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(load_callback_property, 5, 1); 1093e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1094e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return true; 1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadInterceptor(JSObject* object, 10997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch JSObject* interceptor_holder, 1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupResult* lookup, 1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register name_reg, 1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 11053bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String* name, 1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 11087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(interceptor_holder->HasNamedInterceptor()); 11097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); 11107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the receiver isn't a smi. 11127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ BranchOnSmi(receiver, miss); 11137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // So far the most popular follow ups for interceptor loads are FIELD 11157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // and CALLBACKS, so inline only them, other cases may be added 11167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // later. 11177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch bool compile_followup_inline = false; 11187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (lookup->IsProperty() && lookup->IsCacheable()) { 11197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (lookup->type() == FIELD) { 11207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch compile_followup_inline = true; 11217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else if (lookup->type() == CALLBACKS && 11227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch lookup->GetCallbackObject()->IsAccessorInfo() && 11237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL) { 11247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch compile_followup_inline = true; 11257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 11267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 11277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (compile_followup_inline) { 11297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Compile the interceptor call, followed by inline code to load the 11307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // property from further up the prototype chain if the call fails. 11317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps haven't changed. 11327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, 11333bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch1, scratch2, scratch3, 11343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch name, miss); 11357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1)); 11367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Save necessary data before invoking an interceptor. 11387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Requires a frame to make GC aware of pushed pointers. 11397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ EnterInternalFrame(); 11407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { 11427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // CALLBACKS case needs a receiver to be passed into C++ callback. 11437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Push(receiver, holder_reg, name_reg); 11447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 11457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Push(holder_reg, name_reg); 11467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 11477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Invoke an interceptor. Note: map checks from receiver to 11497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // interceptor's holder has been compiled before (see a caller 11507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // of this method.) 11517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch CompileCallLoadPropertyWithInterceptor(masm(), 11527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch receiver, 11537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch holder_reg, 11547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch name_reg, 11557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch interceptor_holder); 11567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check if interceptor provided a value for property. If it's 11587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // the case, return immediately. 11597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label interceptor_failed; 11607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex); 11617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ cmp(r0, scratch1); 11627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ b(eq, &interceptor_failed); 11637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LeaveInternalFrame(); 11647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Ret(); 11657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&interceptor_failed); 11677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(name_reg); 11687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(holder_reg); 11697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { 11707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ pop(receiver); 11717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 11727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LeaveInternalFrame(); 11747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps from interceptor's holder to lookup's holder 11767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // haven't changed. And load lookup's holder into |holder| register. 11777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (interceptor_holder != lookup->holder()) { 11787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch holder_reg = CheckPrototypes(interceptor_holder, 11797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch holder_reg, 11807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch lookup->holder(), 11817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch1, 11827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch2, 11833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch3, 11847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch name, 11857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch miss); 11867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 11877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 11887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (lookup->type() == FIELD) { 11897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // We found FIELD property in prototype chain of interceptor's holder. 11907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Retrieve a field from field's holder. 11917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateFastPropertyLoad(masm(), r0, holder_reg, 11927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch lookup->holder(), lookup->GetFieldIndex()); 11937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Ret(); 11947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 11957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // We found CALLBACKS property in prototype chain of interceptor's 11967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // holder. 11977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(lookup->type() == CALLBACKS); 11987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(lookup->GetCallbackObject()->IsAccessorInfo()); 11997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); 12007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(callback != NULL); 12017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(callback->getter() != NULL); 12027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Tail call to runtime. 12047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Important invariant in CALLBACKS case: the code above must be 12057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // structured to never clobber |receiver| register. 12067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Move(scratch2, Handle<AccessorInfo>(callback)); 12077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // holder_reg is either receiver or scratch1. 12087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (!receiver.is(holder_reg)) { 12097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(scratch1.is(holder_reg)); 12108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Push(receiver, holder_reg); 12118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(scratch3, 12128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang FieldMemOperand(scratch2, AccessorInfo::kDataOffset)); 12138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Push(scratch3, scratch2, name_reg); 12147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 12157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(receiver); 12168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(scratch3, 12178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang FieldMemOperand(scratch2, AccessorInfo::kDataOffset)); 12188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Push(holder_reg, scratch3, scratch2, name_reg); 12197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 12207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ExternalReference ref = 12227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ExternalReference(IC_Utility(IC::kLoadCallbackProperty)); 12237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ TailCallExternalReference(ref, 5, 1); 12247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 12257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { // !compile_followup_inline 12267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Call the runtime system to load the interceptor. 12277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps haven't changed. 12287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, 12293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch1, scratch2, scratch3, 12303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch name, miss); 12317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch PushInterceptorArguments(masm(), receiver, holder_reg, 12327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch name_reg, interceptor_holder); 12337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ExternalReference ref = ExternalReference( 12357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch IC_Utility(IC::kLoadPropertyWithInterceptorForLoad)); 12367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ TailCallExternalReference(ref, 5, 1); 12377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid CallStubCompiler::GenerateNameCheck(String* name, Label* miss) { 12429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (kind_ == Code::KEYED_CALL_IC) { 12439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ cmp(r2, Operand(Handle<String>(name))); 12449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ b(ne, miss); 12459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 12469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 12479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 12489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 124959151504615d929945dc59db37bf1166937748c6Steve Blockvoid CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, 125059151504615d929945dc59db37bf1166937748c6Steve Block JSObject* holder, 125159151504615d929945dc59db37bf1166937748c6Steve Block String* name, 125259151504615d929945dc59db37bf1166937748c6Steve Block Label* miss) { 125359151504615d929945dc59db37bf1166937748c6Steve Block ASSERT(holder->IsGlobalObject()); 125459151504615d929945dc59db37bf1166937748c6Steve Block 125559151504615d929945dc59db37bf1166937748c6Steve Block // Get the number of arguments. 125659151504615d929945dc59db37bf1166937748c6Steve Block const int argc = arguments().immediate(); 125759151504615d929945dc59db37bf1166937748c6Steve Block 125859151504615d929945dc59db37bf1166937748c6Steve Block // Get the receiver from the stack. 125959151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(r0, MemOperand(sp, argc * kPointerSize)); 126059151504615d929945dc59db37bf1166937748c6Steve Block 126159151504615d929945dc59db37bf1166937748c6Steve Block // If the object is the holder then we know that it's a global 126259151504615d929945dc59db37bf1166937748c6Steve Block // object which can only happen for contextual calls. In this case, 126359151504615d929945dc59db37bf1166937748c6Steve Block // the receiver cannot be a smi. 126459151504615d929945dc59db37bf1166937748c6Steve Block if (object != holder) { 126559151504615d929945dc59db37bf1166937748c6Steve Block __ tst(r0, Operand(kSmiTagMask)); 126659151504615d929945dc59db37bf1166937748c6Steve Block __ b(eq, miss); 126759151504615d929945dc59db37bf1166937748c6Steve Block } 126859151504615d929945dc59db37bf1166937748c6Steve Block 126959151504615d929945dc59db37bf1166937748c6Steve Block // Check that the maps haven't changed. 127059151504615d929945dc59db37bf1166937748c6Steve Block CheckPrototypes(object, r0, holder, r3, r1, r4, name, miss); 127159151504615d929945dc59db37bf1166937748c6Steve Block} 127259151504615d929945dc59db37bf1166937748c6Steve Block 127359151504615d929945dc59db37bf1166937748c6Steve Block 127459151504615d929945dc59db37bf1166937748c6Steve Blockvoid CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, 127559151504615d929945dc59db37bf1166937748c6Steve Block JSFunction* function, 127659151504615d929945dc59db37bf1166937748c6Steve Block Label* miss) { 127759151504615d929945dc59db37bf1166937748c6Steve Block // Get the value from the cell. 127859151504615d929945dc59db37bf1166937748c6Steve Block __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); 127959151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); 128059151504615d929945dc59db37bf1166937748c6Steve Block 128159151504615d929945dc59db37bf1166937748c6Steve Block // Check that the cell contains the same function. 128259151504615d929945dc59db37bf1166937748c6Steve Block if (Heap::InNewSpace(function)) { 128359151504615d929945dc59db37bf1166937748c6Steve Block // We can't embed a pointer to a function in new space so we have 128459151504615d929945dc59db37bf1166937748c6Steve Block // to verify that the shared function info is unchanged. This has 128559151504615d929945dc59db37bf1166937748c6Steve Block // the nice side effect that multiple closures based on the same 128659151504615d929945dc59db37bf1166937748c6Steve Block // function can all use this call IC. Before we load through the 128759151504615d929945dc59db37bf1166937748c6Steve Block // function, we have to verify that it still is a function. 128859151504615d929945dc59db37bf1166937748c6Steve Block __ tst(r1, Operand(kSmiTagMask)); 128959151504615d929945dc59db37bf1166937748c6Steve Block __ b(eq, miss); 129059151504615d929945dc59db37bf1166937748c6Steve Block __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); 129159151504615d929945dc59db37bf1166937748c6Steve Block __ b(ne, miss); 129259151504615d929945dc59db37bf1166937748c6Steve Block 129359151504615d929945dc59db37bf1166937748c6Steve Block // Check the shared function info. Make sure it hasn't changed. 129459151504615d929945dc59db37bf1166937748c6Steve Block __ Move(r3, Handle<SharedFunctionInfo>(function->shared())); 129559151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 129659151504615d929945dc59db37bf1166937748c6Steve Block __ cmp(r4, r3); 129759151504615d929945dc59db37bf1166937748c6Steve Block __ b(ne, miss); 129859151504615d929945dc59db37bf1166937748c6Steve Block } else { 129959151504615d929945dc59db37bf1166937748c6Steve Block __ cmp(r1, Operand(Handle<JSFunction>(function))); 130059151504615d929945dc59db37bf1166937748c6Steve Block __ b(ne, miss); 130159151504615d929945dc59db37bf1166937748c6Steve Block } 130259151504615d929945dc59db37bf1166937748c6Steve Block} 130359151504615d929945dc59db37bf1166937748c6Steve Block 130459151504615d929945dc59db37bf1166937748c6Steve Block 13055913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* CallStubCompiler::GenerateMissBranch() { 13065913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* obj; 13075913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck { MaybeObject* maybe_obj = 13085913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck StubCache::ComputeCallMiss(arguments().immediate(), kind_); 13095913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_obj->ToObject(&obj)) return maybe_obj; 13105913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 1311bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); 1312bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch return obj; 13137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 13147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13165913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* CallStubCompiler::CompileCallField(JSObject* object, 13175913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSObject* holder, 13185913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index, 13195913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck String* name) { 1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1321402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- r2 : name 1322402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- lr : return address 1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateNameCheck(name, &miss); 13279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver of the function from the stack into r0. 1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(sp, argc * kPointerSize)); 1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r0, Operand(kSmiTagMask)); 1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &miss); 1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do the right check and compute the holder register. 13373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register reg = CheckPrototypes(object, r0, holder, r1, r3, r4, name, &miss); 1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateFastPropertyLoad(masm(), r1, reg, holder, index); 1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke GenerateCallFunction(masm(), object, arguments(), &miss); 1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 13445913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* obj; 13455913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck { MaybeObject* maybe_obj = GenerateMissBranch(); 13465913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_obj->ToObject(&obj)) return maybe_obj; 13475913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(FIELD, name); 1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13545913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, 13555913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSObject* holder, 13565913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSGlobalPropertyCell* cell, 13575913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSFunction* function, 13585913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck String* name) { 13596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 13606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- r2 : name 13616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- lr : return address 13628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 13638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- ... 13648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- sp[argc * 4] : receiver 13656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 13666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 136759151504615d929945dc59db37bf1166937748c6Steve Block // If object is not an array, bail out to regular call. 136859151504615d929945dc59db37bf1166937748c6Steve Block if (!object->IsJSArray() || cell != NULL) return Heap::undefined_value(); 13696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss; 13716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateNameCheck(name, &miss); 13739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 13748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register receiver = r1; 13758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 13766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the receiver from the stack 13776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int argc = arguments().immediate(); 13788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); 13796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the receiver isn't a smi. 13818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ BranchOnSmi(receiver, &miss); 13826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the maps haven't changed. 13848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CheckPrototypes(JSObject::cast(object), receiver, 13858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang holder, r3, r0, r4, name, &miss); 13866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang if (argc == 0) { 13888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Nothing to do, just return the length. 13898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 13908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(argc + 1); 13918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 13928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } else { 13938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label call_builtin; 13948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 13958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register elements = r3; 13968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register end_elements = r5; 13978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 13988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Get the elements array of the object. 13998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); 14008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 14018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check that the elements are in fast mode and writable. 14028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ CheckMap(elements, r0, 14038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Heap::kFixedArrayMapRootIndex, &call_builtin, true); 14048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 14058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang if (argc == 1) { // Otherwise fall through to call the builtin. 14068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label exit, with_write_barrier, attempt_to_grow_elements; 14078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 14088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Get the array's length into r0 and calculate new length. 14098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 14108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang STATIC_ASSERT(kSmiTagSize == 1); 14118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang STATIC_ASSERT(kSmiTag == 0); 14128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ add(r0, r0, Operand(Smi::FromInt(argc))); 14138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 14148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Get the element's length. 14158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset)); 14168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 14178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check if we could survive without allocation. 14188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ cmp(r0, r4); 14198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(gt, &attempt_to_grow_elements); 14208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 14218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Save new length. 14228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 14238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 14248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Push the element. 14258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r4, MemOperand(sp, (argc - 1) * kPointerSize)); 14268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // We may need a register containing the address end_elements below, 14278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // so write back the value in end_elements. 14288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ add(end_elements, elements, 14298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); 14308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const int kEndElementsOffset = 14318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize; 14328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex)); 14338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 14348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check for a smi. 14358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ BranchOnNotSmi(r4, &with_write_barrier); 14368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&exit); 14378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(argc + 1); 14388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 14398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 14408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&with_write_barrier); 14418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ InNewSpace(elements, r4, eq, &exit); 14428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ RecordWriteHelper(elements, end_elements, r4); 14438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(argc + 1); 14448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 14458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 14468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&attempt_to_grow_elements); 14478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // r0: array's length + 1. 14488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // r4: elements' length. 14498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 14508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang if (!FLAG_inline_new) { 14518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&call_builtin); 14528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 14538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 14548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ExternalReference new_space_allocation_top = 14558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ExternalReference::new_space_allocation_top_address(); 14568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ExternalReference new_space_allocation_limit = 14578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ExternalReference::new_space_allocation_limit_address(); 14588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 14598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const int kAllocationDelta = 4; 14608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load top and check if it is the end of elements. 14618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ add(end_elements, elements, 14628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); 14638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ add(end_elements, end_elements, Operand(kEndElementsOffset)); 14648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(r7, Operand(new_space_allocation_top)); 14658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r6, MemOperand(r7)); 14668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ cmp(end_elements, r6); 14678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(ne, &call_builtin); 14688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 14698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(r9, Operand(new_space_allocation_limit)); 14708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r9, MemOperand(r9)); 14718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ add(r6, r6, Operand(kAllocationDelta * kPointerSize)); 14728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ cmp(r6, r9); 14738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(hi, &call_builtin); 14748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 14758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // We fit and could grow elements. 14768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Update new_space_allocation_top. 14778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(r6, MemOperand(r7)); 14788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Push the argument. 14798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r6, MemOperand(sp, (argc - 1) * kPointerSize)); 14808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(r6, MemOperand(end_elements)); 14818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Fill the rest with holes. 14828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ LoadRoot(r6, Heap::kTheHoleValueRootIndex); 14838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang for (int i = 1; i < kAllocationDelta; i++) { 14848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(r6, MemOperand(end_elements, i * kPointerSize)); 14858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 14868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 14878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Update elements' and array's sizes. 14888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 14898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ add(r4, r4, Operand(Smi::FromInt(kAllocationDelta))); 14908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(r4, FieldMemOperand(elements, FixedArray::kLengthOffset)); 14918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 14928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Elements are in new space, so write barrier is not required. 14938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(argc + 1); 14948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 14958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 14968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&call_builtin); 14978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush), 14988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang argc + 1, 14998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1); 15008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 15016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Handle call cache miss. 15036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss); 15045913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* obj; 15055913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck { MaybeObject* maybe_obj = GenerateMissBranch(); 15065913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_obj->ToObject(&obj)) return maybe_obj; 15075913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 15086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return the generated code. 151025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen return GetCode(function); 15116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 15126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15145913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, 15155913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSObject* holder, 15165913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSGlobalPropertyCell* cell, 15175913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSFunction* function, 15185913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck String* name) { 1519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1520402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- r2 : name 1521402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- lr : return address 15228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 15238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- ... 15248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- sp[argc * 4] : receiver 1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 15266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 152759151504615d929945dc59db37bf1166937748c6Steve Block // If object is not an array, bail out to regular call. 152859151504615d929945dc59db37bf1166937748c6Steve Block if (!object->IsJSArray() || cell != NULL) return Heap::undefined_value(); 15296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label miss, return_undefined, call_builtin; 15318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 15328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register receiver = r1; 15338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register elements = r3; 1534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateNameCheck(name, &miss); 15369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 1537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver from the stack 1538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 15398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); 1540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 15428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ BranchOnSmi(receiver, &miss); 15436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the maps haven't changed. 15458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CheckPrototypes(JSObject::cast(object), 15468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang receiver, holder, elements, r4, r0, name, &miss); 15478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 15488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Get the elements array of the object. 15498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); 15506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check that the elements are in fast mode and writable. 15528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ CheckMap(elements, r0, Heap::kFixedArrayMapRootIndex, &call_builtin, true); 15538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 15548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Get the array's length into r4 and calculate new length. 15558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r4, FieldMemOperand(receiver, JSArray::kLengthOffset)); 15568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ sub(r4, r4, Operand(Smi::FromInt(1)), SetCC); 15578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(lt, &return_undefined); 15588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 15598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Get the last element. 15608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ LoadRoot(r6, Heap::kTheHoleValueRootIndex); 15618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang STATIC_ASSERT(kSmiTagSize == 1); 15628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang STATIC_ASSERT(kSmiTag == 0); 15638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // We can't address the last element in one operation. Compute the more 15648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // expensive shift first, and use an offset later on. 15658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ add(elements, elements, Operand(r4, LSL, kPointerSizeLog2 - kSmiTagSize)); 15668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r0, MemOperand(elements, FixedArray::kHeaderSize - kHeapObjectTag)); 15678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ cmp(r0, r6); 15688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(eq, &call_builtin); 15698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 15708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Set the array's length. 15718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(r4, FieldMemOperand(receiver, JSArray::kLengthOffset)); 15728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 15738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Fill with the hole. 15748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(r6, MemOperand(elements, FixedArray::kHeaderSize - kHeapObjectTag)); 15758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(argc + 1); 15768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 15778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 15788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&return_undefined); 15798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 15808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(argc + 1); 15818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 15828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 15838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&call_builtin); 15846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop), 15856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block argc + 1, 15866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1); 15876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Handle call cache miss. 15896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss); 15905913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* obj; 15915913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck { MaybeObject* maybe_obj = GenerateMissBranch(); 15925913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_obj->ToObject(&obj)) return maybe_obj; 15935913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 15946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return the generated code. 159625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen return GetCode(function); 15976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 15986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16005913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( 160159151504615d929945dc59db37bf1166937748c6Steve Block Object* object, 160259151504615d929945dc59db37bf1166937748c6Steve Block JSObject* holder, 160359151504615d929945dc59db37bf1166937748c6Steve Block JSGlobalPropertyCell* cell, 160459151504615d929945dc59db37bf1166937748c6Steve Block JSFunction* function, 160559151504615d929945dc59db37bf1166937748c6Steve Block String* name) { 160680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ----------- S t a t e ------------- 160780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- r2 : function name 160880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- lr : return address 160980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 161080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- ... 161180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- sp[argc * 4] : receiver 161280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ----------------------------------- 161380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 161480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // If object is not a string, bail out to regular call. 161559151504615d929945dc59db37bf1166937748c6Steve Block if (!object->IsString() || cell != NULL) return Heap::undefined_value(); 161680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 161780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen const int argc = arguments().immediate(); 161880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 161980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label miss; 162080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label index_out_of_range; 162180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen GenerateNameCheck(name, &miss); 162280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 162380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check that the maps starting from the prototype haven't changed. 162480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen GenerateDirectLoadGlobalFunctionPrototype(masm(), 162580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Context::STRING_FUNCTION_INDEX, 16260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen r0, 16270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &miss); 162880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(object != holder); 162980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, 163080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen r1, r3, r4, name, &miss); 163180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 163280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Register receiver = r1; 163380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Register index = r4; 163480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Register scratch = r3; 163580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Register result = r0; 163680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); 163780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (argc > 0) { 163880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize)); 163980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 164080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadRoot(index, Heap::kUndefinedValueRootIndex); 164180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 164280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 164380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen StringCharCodeAtGenerator char_code_at_generator(receiver, 164480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen index, 164580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen scratch, 164680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen result, 164780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen &miss, // When not a string. 164880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen &miss, // When not a number. 164980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen &index_out_of_range, 165080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen STRING_INDEX_IS_NUMBER); 165180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen char_code_at_generator.GenerateFast(masm()); 165280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Drop(argc + 1); 165380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Ret(); 165480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 165580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ICRuntimeCallHelper call_helper; 165680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen char_code_at_generator.GenerateSlow(masm(), call_helper); 165780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 165880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&index_out_of_range); 165980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadRoot(r0, Heap::kNanValueRootIndex); 166080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Drop(argc + 1); 166180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Ret(); 166280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 166380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&miss); 16645913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* obj; 16655913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck { MaybeObject* maybe_obj = GenerateMissBranch(); 16665913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_obj->ToObject(&obj)) return maybe_obj; 16675913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 166880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 166980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Return the generated code. 167080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen return GetCode(function); 16717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 16727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 16745913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* CallStubCompiler::CompileStringCharAtCall( 16755913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* object, 16765913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSObject* holder, 16775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSGlobalPropertyCell* cell, 16785913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSFunction* function, 16795913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck String* name) { 168080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ----------- S t a t e ------------- 168180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- r2 : function name 168280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- lr : return address 168380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 168480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- ... 168580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- sp[argc * 4] : receiver 168680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ----------------------------------- 168780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 168880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // If object is not a string, bail out to regular call. 168959151504615d929945dc59db37bf1166937748c6Steve Block if (!object->IsString() || cell != NULL) return Heap::undefined_value(); 169080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 169180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen const int argc = arguments().immediate(); 169280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 169380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label miss; 169480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label index_out_of_range; 169580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 169680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen GenerateNameCheck(name, &miss); 169780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 169880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check that the maps starting from the prototype haven't changed. 169980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen GenerateDirectLoadGlobalFunctionPrototype(masm(), 170080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Context::STRING_FUNCTION_INDEX, 17010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen r0, 17020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &miss); 170380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ASSERT(object != holder); 170480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, 170580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen r1, r3, r4, name, &miss); 170680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 170780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Register receiver = r0; 170880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Register index = r4; 170980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Register scratch1 = r1; 171080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Register scratch2 = r3; 171180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Register result = r0; 171280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); 171380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (argc > 0) { 171480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize)); 171580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 171680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadRoot(index, Heap::kUndefinedValueRootIndex); 171780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 171880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 171980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen StringCharAtGenerator char_at_generator(receiver, 172080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen index, 172180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen scratch1, 172280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen scratch2, 172380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen result, 172480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen &miss, // When not a string. 172580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen &miss, // When not a number. 172680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen &index_out_of_range, 172780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen STRING_INDEX_IS_NUMBER); 172880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen char_at_generator.GenerateFast(masm()); 172980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Drop(argc + 1); 173080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Ret(); 173180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 173280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ICRuntimeCallHelper call_helper; 173380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen char_at_generator.GenerateSlow(masm(), call_helper); 173480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 173580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&index_out_of_range); 173680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadRoot(r0, Heap::kEmptyStringRootIndex); 173780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Drop(argc + 1); 173880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Ret(); 173980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 174080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&miss); 17415913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* obj; 17425913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck { MaybeObject* maybe_obj = GenerateMissBranch(); 17435913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_obj->ToObject(&obj)) return maybe_obj; 17445913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 174580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 174680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Return the generated code. 174780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen return GetCode(function); 17487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 17497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 17515913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* CallStubCompiler::CompileStringFromCharCodeCall( 175259151504615d929945dc59db37bf1166937748c6Steve Block Object* object, 175359151504615d929945dc59db37bf1166937748c6Steve Block JSObject* holder, 175459151504615d929945dc59db37bf1166937748c6Steve Block JSGlobalPropertyCell* cell, 175559151504615d929945dc59db37bf1166937748c6Steve Block JSFunction* function, 175659151504615d929945dc59db37bf1166937748c6Steve Block String* name) { 175759151504615d929945dc59db37bf1166937748c6Steve Block // ----------- S t a t e ------------- 175859151504615d929945dc59db37bf1166937748c6Steve Block // -- r2 : function name 175959151504615d929945dc59db37bf1166937748c6Steve Block // -- lr : return address 176059151504615d929945dc59db37bf1166937748c6Steve Block // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 176159151504615d929945dc59db37bf1166937748c6Steve Block // -- ... 176259151504615d929945dc59db37bf1166937748c6Steve Block // -- sp[argc * 4] : receiver 176359151504615d929945dc59db37bf1166937748c6Steve Block // ----------------------------------- 176459151504615d929945dc59db37bf1166937748c6Steve Block 176559151504615d929945dc59db37bf1166937748c6Steve Block const int argc = arguments().immediate(); 176659151504615d929945dc59db37bf1166937748c6Steve Block 176759151504615d929945dc59db37bf1166937748c6Steve Block // If the object is not a JSObject or we got an unexpected number of 176859151504615d929945dc59db37bf1166937748c6Steve Block // arguments, bail out to the regular call. 176959151504615d929945dc59db37bf1166937748c6Steve Block if (!object->IsJSObject() || argc != 1) return Heap::undefined_value(); 177059151504615d929945dc59db37bf1166937748c6Steve Block 177159151504615d929945dc59db37bf1166937748c6Steve Block Label miss; 177259151504615d929945dc59db37bf1166937748c6Steve Block GenerateNameCheck(name, &miss); 177359151504615d929945dc59db37bf1166937748c6Steve Block 177459151504615d929945dc59db37bf1166937748c6Steve Block if (cell == NULL) { 177559151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); 177659151504615d929945dc59db37bf1166937748c6Steve Block 177759151504615d929945dc59db37bf1166937748c6Steve Block STATIC_ASSERT(kSmiTag == 0); 177859151504615d929945dc59db37bf1166937748c6Steve Block __ tst(r1, Operand(kSmiTagMask)); 177959151504615d929945dc59db37bf1166937748c6Steve Block __ b(eq, &miss); 178059151504615d929945dc59db37bf1166937748c6Steve Block 178159151504615d929945dc59db37bf1166937748c6Steve Block CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, 178259151504615d929945dc59db37bf1166937748c6Steve Block &miss); 178359151504615d929945dc59db37bf1166937748c6Steve Block } else { 178459151504615d929945dc59db37bf1166937748c6Steve Block ASSERT(cell->value() == function); 178559151504615d929945dc59db37bf1166937748c6Steve Block GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); 178659151504615d929945dc59db37bf1166937748c6Steve Block GenerateLoadFunctionFromCell(cell, function, &miss); 178759151504615d929945dc59db37bf1166937748c6Steve Block } 178859151504615d929945dc59db37bf1166937748c6Steve Block 178959151504615d929945dc59db37bf1166937748c6Steve Block // Load the char code argument. 179059151504615d929945dc59db37bf1166937748c6Steve Block Register code = r1; 179159151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(code, MemOperand(sp, 0 * kPointerSize)); 179259151504615d929945dc59db37bf1166937748c6Steve Block 179359151504615d929945dc59db37bf1166937748c6Steve Block // Check the code is a smi. 179459151504615d929945dc59db37bf1166937748c6Steve Block Label slow; 179559151504615d929945dc59db37bf1166937748c6Steve Block STATIC_ASSERT(kSmiTag == 0); 179659151504615d929945dc59db37bf1166937748c6Steve Block __ tst(code, Operand(kSmiTagMask)); 179759151504615d929945dc59db37bf1166937748c6Steve Block __ b(ne, &slow); 179859151504615d929945dc59db37bf1166937748c6Steve Block 179959151504615d929945dc59db37bf1166937748c6Steve Block // Convert the smi code to uint16. 180059151504615d929945dc59db37bf1166937748c6Steve Block __ and_(code, code, Operand(Smi::FromInt(0xffff))); 180159151504615d929945dc59db37bf1166937748c6Steve Block 180259151504615d929945dc59db37bf1166937748c6Steve Block StringCharFromCodeGenerator char_from_code_generator(code, r0); 180359151504615d929945dc59db37bf1166937748c6Steve Block char_from_code_generator.GenerateFast(masm()); 180459151504615d929945dc59db37bf1166937748c6Steve Block __ Drop(argc + 1); 180559151504615d929945dc59db37bf1166937748c6Steve Block __ Ret(); 180659151504615d929945dc59db37bf1166937748c6Steve Block 180759151504615d929945dc59db37bf1166937748c6Steve Block ICRuntimeCallHelper call_helper; 180859151504615d929945dc59db37bf1166937748c6Steve Block char_from_code_generator.GenerateSlow(masm(), call_helper); 180959151504615d929945dc59db37bf1166937748c6Steve Block 181059151504615d929945dc59db37bf1166937748c6Steve Block // Tail call the full function. We do not have to patch the receiver 181159151504615d929945dc59db37bf1166937748c6Steve Block // because the function makes no use of it. 181259151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&slow); 181359151504615d929945dc59db37bf1166937748c6Steve Block __ InvokeFunction(function, arguments(), JUMP_FUNCTION); 181459151504615d929945dc59db37bf1166937748c6Steve Block 181559151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&miss); 181659151504615d929945dc59db37bf1166937748c6Steve Block // r2: function name. 18175913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* obj; 18185913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck { MaybeObject* maybe_obj = GenerateMissBranch(); 18195913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_obj->ToObject(&obj)) return maybe_obj; 18205913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 182159151504615d929945dc59db37bf1166937748c6Steve Block 182259151504615d929945dc59db37bf1166937748c6Steve Block // Return the generated code. 182359151504615d929945dc59db37bf1166937748c6Steve Block return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); 182459151504615d929945dc59db37bf1166937748c6Steve Block} 182559151504615d929945dc59db37bf1166937748c6Steve Block 182659151504615d929945dc59db37bf1166937748c6Steve Block 18275913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object, 18285913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSObject* holder, 18295913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSGlobalPropertyCell* cell, 18305913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSFunction* function, 18315913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck String* name) { 18328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // ----------- S t a t e ------------- 18338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- r2 : function name 18348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- lr : return address 18358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 18368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- ... 18378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- sp[argc * 4] : receiver 18388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // ----------------------------------- 18398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 18408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang if (!CpuFeatures::IsSupported(VFP3)) return Heap::undefined_value(); 18418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CpuFeatures::Scope scope_vfp3(VFP3); 18428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 18438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const int argc = arguments().immediate(); 18448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 18458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // If the object is not a JSObject or we got an unexpected number of 18468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // arguments, bail out to the regular call. 18478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang if (!object->IsJSObject() || argc != 1) return Heap::undefined_value(); 18488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 18498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label miss, slow; 18508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GenerateNameCheck(name, &miss); 18518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 18528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang if (cell == NULL) { 18538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); 18548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 18558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang STATIC_ASSERT(kSmiTag == 0); 18568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ BranchOnSmi(r1, &miss); 18578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 18588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, 18598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang &miss); 18608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } else { 18618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ASSERT(cell->value() == function); 18628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); 18638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GenerateLoadFunctionFromCell(cell, function, &miss); 18648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 18658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 18668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load the (only) argument into r0. 18678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); 18688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 18698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // If the argument is a smi, just return. 18708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang STATIC_ASSERT(kSmiTag == 0); 18718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ tst(r0, Operand(kSmiTagMask)); 18728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(argc + 1, eq); 18738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(eq); 18748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 18758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, &slow, true); 18768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 18778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label wont_fit_smi, no_vfp_exception, restore_fpscr_and_return; 18788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 18798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // If vfp3 is enabled, we use the fpu rounding with the RM (round towards 18808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // minus infinity) mode. 18818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 18828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load the HeapNumber value. 18838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // We will need access to the value in the core registers, so we load it 18848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // with ldrd and move it to the fpu. It also spares a sub instruction for 18858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // updating the HeapNumber value address, as vldr expects a multiple 18868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // of 4 offset. 18878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ldrd(r4, r5, FieldMemOperand(r0, HeapNumber::kValueOffset)); 18888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ vmov(d1, r4, r5); 18898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 18908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Backup FPSCR. 18918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ vmrs(r3); 18928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Set custom FPCSR: 18938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // - Set rounding mode to "Round towards Minus Infinity" 18948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // (ie bits [23:22] = 0b10). 18958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // - Clear vfp cumulative exception flags (bits [3:0]). 18968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // - Make sure Flush-to-zero mode control bit is unset (bit 22). 18978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bic(r9, r3, 18988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Operand(kVFPExceptionMask | kVFPRoundingModeMask | kVFPFlushToZeroMask)); 18998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ orr(r9, r9, Operand(kVFPRoundToMinusInfinityBits)); 19008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ vmsr(r9); 19018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 19028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Convert the argument to an integer. 19038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ vcvt_s32_f64(s0, d1, Assembler::FPSCRRounding, al); 19048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 19058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Use vcvt latency to start checking for special cases. 19068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Get the argument exponent and clear the sign bit. 19078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bic(r6, r5, Operand(HeapNumber::kSignMask)); 19088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(r6, Operand(r6, LSR, HeapNumber::kMantissaBitsInTopWord)); 19098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 19108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Retrieve FPSCR and check for vfp exceptions. 19118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ vmrs(r9); 19128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ tst(r9, Operand(kVFPExceptionMask)); 19138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&no_vfp_exception, eq); 19148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 19158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check for NaN, Infinity, and -Infinity. 19168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // They are invariant through a Math.Floor call, so just 19178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // return the original argument. 19188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ sub(r7, r6, Operand(HeapNumber::kExponentMask 19198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang >> HeapNumber::kMantissaBitsInTopWord), SetCC); 19208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&restore_fpscr_and_return, eq); 19218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // We had an overflow or underflow in the conversion. Check if we 19228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // have a big exponent. 19238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ cmp(r7, Operand(HeapNumber::kMantissaBits)); 19248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // If greater or equal, the argument is already round and in r0. 19258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&restore_fpscr_and_return, ge); 19268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&slow); 19278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 19288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&no_vfp_exception); 19298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Move the result back to general purpose register r0. 19308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ vmov(r0, s0); 19318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check if the result fits into a smi. 19328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ add(r1, r0, Operand(0x40000000), SetCC); 19338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&wont_fit_smi, mi); 19348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Tag the result. 19358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang STATIC_ASSERT(kSmiTag == 0); 19368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(r0, Operand(r0, LSL, kSmiTagSize)); 19378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 19388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check for -0. 19398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ cmp(r0, Operand(0)); 19408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&restore_fpscr_and_return, ne); 19418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // r5 already holds the HeapNumber exponent. 19428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ tst(r5, Operand(HeapNumber::kSignMask)); 19438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // If our HeapNumber is negative it was -0, so load its address and return. 19448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Else r0 is loaded with 0, so we can also just return. 19458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r0, MemOperand(sp, 0 * kPointerSize), ne); 19468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 19478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&restore_fpscr_and_return); 19488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Restore FPSCR and return. 19498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ vmsr(r3); 19508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(argc + 1); 19518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 19528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 19538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&wont_fit_smi); 19548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&slow); 19558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Restore FPCSR and fall to slow case. 19568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ vmsr(r3); 19578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 19588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Tail call the full function. We do not have to patch the receiver 19598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // because the function makes no use of it. 19608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ InvokeFunction(function, arguments(), JUMP_FUNCTION); 19618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 19628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&miss); 19638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // r2: function name. 19648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang MaybeObject* obj = GenerateMissBranch(); 19658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang if (obj->IsFailure()) return obj; 19668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 19678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Return the generated code. 19688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); 19690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 19700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 19725913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object, 19735913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSObject* holder, 19745913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSGlobalPropertyCell* cell, 19755913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSFunction* function, 19765913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck String* name) { 1977f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // ----------- S t a t e ------------- 1978f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- r2 : function name 1979f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- lr : return address 1980f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 1981f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- ... 1982f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- sp[argc * 4] : receiver 1983f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // ----------------------------------- 1984f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 1985f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch const int argc = arguments().immediate(); 1986f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 1987f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // If the object is not a JSObject or we got an unexpected number of 1988f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // arguments, bail out to the regular call. 1989f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if (!object->IsJSObject() || argc != 1) return Heap::undefined_value(); 1990f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 1991f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Label miss; 1992f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch GenerateNameCheck(name, &miss); 1993f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 1994f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if (cell == NULL) { 1995f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); 1996f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 1997f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch STATIC_ASSERT(kSmiTag == 0); 1998f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ tst(r1, Operand(kSmiTagMask)); 1999f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ b(eq, &miss); 2000f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2001f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, 2002f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch &miss); 2003f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch } else { 2004f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ASSERT(cell->value() == function); 2005f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); 2006f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch GenerateLoadFunctionFromCell(cell, function, &miss); 2007f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch } 2008f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2009f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Load the (only) argument into r0. 2010f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); 2011f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2012f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Check if the argument is a smi. 2013f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Label not_smi; 2014f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch STATIC_ASSERT(kSmiTag == 0); 2015f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ BranchOnNotSmi(r0, ¬_smi); 2016f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2017f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Do bitwise not or do nothing depending on the sign of the 2018f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // argument. 2019f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ eor(r1, r0, Operand(r0, ASR, kBitsPerInt - 1)); 2020f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2021f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Add 1 or do nothing depending on the sign of the argument. 2022f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ sub(r0, r1, Operand(r0, ASR, kBitsPerInt - 1), SetCC); 2023f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2024f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // If the result is still negative, go to the slow case. 2025f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // This only happens for the most negative smi. 2026f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Label slow; 2027f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ b(mi, &slow); 2028f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2029f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Smi case done. 2030f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ Drop(argc + 1); 2031f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ Ret(); 2032f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2033f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Check if the argument is a heap number and load its exponent and 2034f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // sign. 2035f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(¬_smi); 2036f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, &slow, true); 2037f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ ldr(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset)); 2038f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2039f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Check the sign of the argument. If the argument is positive, 2040f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // just return it. 2041f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Label negative_sign; 2042f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ tst(r1, Operand(HeapNumber::kSignMask)); 2043f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ b(ne, &negative_sign); 2044f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ Drop(argc + 1); 2045f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ Ret(); 2046f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2047f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // If the argument is negative, clear the sign, and return a new 2048f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // number. 2049f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(&negative_sign); 2050f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ eor(r1, r1, Operand(HeapNumber::kSignMask)); 2051f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); 2052f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); 2053f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ AllocateHeapNumber(r0, r4, r5, r6, &slow); 2054f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ str(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset)); 2055f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ str(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); 2056f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ Drop(argc + 1); 2057f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ Ret(); 2058f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2059f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Tail call the full function. We do not have to patch the receiver 2060f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // because the function makes no use of it. 2061f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(&slow); 2062f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ InvokeFunction(function, arguments(), JUMP_FUNCTION); 2063f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2064f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(&miss); 2065f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // r2: function name. 20665913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* obj; 20675913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck { MaybeObject* maybe_obj = GenerateMissBranch(); 20685913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_obj->ToObject(&obj)) return maybe_obj; 20695913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 2070f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2071f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Return the generated code. 2072f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); 2073f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch} 2074f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2075f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 20765913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* CallStubCompiler::CompileCallConstant(Object* object, 20775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSObject* holder, 20785913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSFunction* function, 20795913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck String* name, 20805913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck CheckType check) { 20816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 20826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- r2 : name 20836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- lr : return address 20846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 20856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SharedFunctionInfo* function_info = function->shared(); 20866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (function_info->HasCustomCallGenerator()) { 208725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen const int id = function_info->custom_call_generator_id(); 20885913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck MaybeObject* maybe_result = CompileCustomCall( 208959151504615d929945dc59db37bf1166937748c6Steve Block id, object, holder, NULL, function, name); 20905913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* result; 20915913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_result->ToObject(&result)) return maybe_result; 20926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // undefined means bail out to regular compiler. 20936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (!result->IsUndefined()) { 20946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return result; 20956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 20966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 20976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 20986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss_in_smi_check; 20996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 21009dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateNameCheck(name, &miss_in_smi_check); 21019dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 21026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the receiver from the stack 21036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int argc = arguments().immediate(); 21046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ldr(r1, MemOperand(sp, argc * kPointerSize)); 21056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 21066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the receiver isn't a smi. 2107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check != NUMBER_CHECK) { 2108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r1, Operand(kSmiTagMask)); 21096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ b(eq, &miss_in_smi_check); 2110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure that it's okay not to patch the on stack receiver 2113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // unless we're doing a receiver map check. 2114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); 2115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 21166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CallOptimization optimization(function); 21176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int depth = kInvalidProtoDepth; 21186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss; 21196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (check) { 2121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case RECEIVER_MAP_CHECK: 21226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ IncrementCounter(&Counters::call_const, 1, r0, r3); 21236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 21246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (optimization.is_simple_api_call() && !object->IsGlobalObject()) { 21256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block depth = optimization.GetPrototypeDepthOfExpectedType( 21266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSObject::cast(object), holder); 21276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 21286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 21296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (depth != kInvalidProtoDepth) { 21306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ IncrementCounter(&Counters::call_const_fast_api, 1, r0, r3); 21316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ReserveSpaceForFastApiCall(masm(), r0); 21326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 21336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 21353bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, 21366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block depth, &miss); 2137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack with the global proxy if 2139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // necessary. 2140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsGlobalObject()) { 21416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(depth == kInvalidProtoDepth); 2142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); 2143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r3, MemOperand(sp, argc * kPointerSize)); 2144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 2146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case STRING_CHECK: 2148e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!function->IsBuiltin()) { 2149e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Calling non-builtins with a value as receiver requires boxing. 2150e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(&miss); 2151e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 2152e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the object is a two-byte string or a symbol. 2153402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE); 2154e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ b(hs, &miss); 2155e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the maps starting from the prototype haven't changed. 21567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype( 21570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen masm(), Context::STRING_FUNCTION_INDEX, r0, &miss); 2158402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, 21593bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch r1, r4, name, &miss); 2160e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 2162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case NUMBER_CHECK: { 2164e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!function->IsBuiltin()) { 2165e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Calling non-builtins with a value as receiver requires boxing. 2166e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(&miss); 2167e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 2168e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label fast; 2169e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the object is a smi or a heap number. 2170e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ tst(r1, Operand(kSmiTagMask)); 2171e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ b(eq, &fast); 2172402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE); 2173e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ b(ne, &miss); 2174e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&fast); 2175e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the maps starting from the prototype haven't changed. 21767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype( 21770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss); 2178402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, 21793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch r1, r4, name, &miss); 2180e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 2182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case BOOLEAN_CHECK: { 2185e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (!function->IsBuiltin()) { 2186e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Calling non-builtins with a value as receiver requires boxing. 2187e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ jmp(&miss); 2188e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 2189e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label fast; 2190e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the object is a boolean. 2191e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadRoot(ip, Heap::kTrueValueRootIndex); 2192e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(r1, ip); 2193e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ b(eq, &fast); 2194e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadRoot(ip, Heap::kFalseValueRootIndex); 2195e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(r1, ip); 2196e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ b(ne, &miss); 2197e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&fast); 2198e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the maps starting from the prototype haven't changed. 21997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype( 22000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen masm(), Context::BOOLEAN_FUNCTION_INDEX, r0, &miss); 2201402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, 22023bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch r1, r4, name, &miss); 2203e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 2205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 2208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 2209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 22116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (depth != kInvalidProtoDepth) { 22126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GenerateFastApiCall(masm(), optimization, argc); 22136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 22146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ InvokeFunction(function, arguments(), JUMP_FUNCTION); 22156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 2218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 22196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (depth != kInvalidProtoDepth) { 22206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FreeSpaceForFastApiCall(masm()); 22216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 22226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 22236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss_in_smi_check); 22245913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* obj; 22255913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck { MaybeObject* maybe_obj = GenerateMissBranch(); 22265913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_obj->ToObject(&obj)) return maybe_obj; 22275913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 2228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 223025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen return GetCode(function); 2231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 22345913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, 22355913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSObject* holder, 22365913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck String* name) { 2237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2238402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- r2 : name 2239402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- lr : return address 2240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 22426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss; 2243402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 22449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateNameCheck(name, &miss); 22459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 22464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Get the number of arguments. 22474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke const int argc = arguments().immediate(); 22484515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 22494515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke LookupResult lookup; 22504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke LookupPostInterceptor(holder, name, &lookup); 22514515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 22526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the receiver from the stack. 22536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ldr(r1, MemOperand(sp, argc * kPointerSize)); 2254402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 22556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CallInterceptorCompiler compiler(this, arguments(), r2); 22566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block compiler.Compile(masm(), 22576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block object, 22586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block holder, 22596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block name, 22606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block &lookup, 22616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block r1, 22626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block r3, 22636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block r4, 22643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch r0, 22656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block &miss); 2266402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 2267402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Move returned value, the function to call, to r1. 2268402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(r1, r0); 22694515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Restore receiver. 22706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ldr(r0, MemOperand(sp, argc * kPointerSize)); 22714515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 22724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke GenerateCallFunction(masm(), object, arguments(), &miss); 2273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 2275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 22765913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* obj; 22775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck { MaybeObject* maybe_obj = GenerateMissBranch(); 22785913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_obj->ToObject(&obj)) return maybe_obj; 22795913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 2280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 22865913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object, 22875913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck GlobalObject* holder, 22885913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSGlobalPropertyCell* cell, 22895913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSFunction* function, 22905913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck String* name) { 2291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2292402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- r2 : name 2293402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- lr : return address 2294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 229559151504615d929945dc59db37bf1166937748c6Steve Block 229659151504615d929945dc59db37bf1166937748c6Steve Block SharedFunctionInfo* function_info = function->shared(); 229759151504615d929945dc59db37bf1166937748c6Steve Block if (function_info->HasCustomCallGenerator()) { 229859151504615d929945dc59db37bf1166937748c6Steve Block const int id = function_info->custom_call_generator_id(); 22995913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck MaybeObject* maybe_result = CompileCustomCall( 230059151504615d929945dc59db37bf1166937748c6Steve Block id, object, holder, cell, function, name); 23015913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* result; 23025913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_result->ToObject(&result)) return maybe_result; 230359151504615d929945dc59db37bf1166937748c6Steve Block // undefined means bail out to regular compiler. 230459151504615d929945dc59db37bf1166937748c6Steve Block if (!result->IsUndefined()) return result; 230559151504615d929945dc59db37bf1166937748c6Steve Block } 230659151504615d929945dc59db37bf1166937748c6Steve Block 2307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23099dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateNameCheck(name, &miss); 23109dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 2311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the number of arguments. 2312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 2313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 231459151504615d929945dc59db37bf1166937748c6Steve Block GenerateGlobalReceiverCheck(object, holder, name, &miss); 2315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 231659151504615d929945dc59db37bf1166937748c6Steve Block GenerateLoadFunctionFromCell(cell, function, &miss); 2317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack with the global proxy if 2319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // necessary. 2320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsGlobalObject()) { 2321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); 2322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r3, MemOperand(sp, argc * kPointerSize)); 2323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Setup the context (function already in r1). 2326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 2327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the cached code (tail call). 23296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ IncrementCounter(&Counters::call_global_inline, 1, r3, r4); 2330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(function->is_compiled()); 2331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> code(function->code()); 2332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount expected(function->shared()->formal_parameter_count()); 2333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeCode(code, expected, arguments(), 2334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::CODE_TARGET, JUMP_FUNCTION); 2335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 2337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::call_global_inline_miss, 1, r1, r3); 23395913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* obj; 23405913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck { MaybeObject* maybe_obj = GenerateMissBranch(); 23415913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_obj->ToObject(&obj)) return maybe_obj; 23425913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 2343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(NORMAL, name); 2346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23495913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* StoreStubCompiler::CompileStoreField(JSObject* object, 23505913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index, 23515913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Map* transition, 23525913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck String* name) { 2353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : value 2355402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- r1 : receiver 2356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 2357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateStoreField(masm(), 2362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object, 2363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block index, 2364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block transition, 2365402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu r1, r2, r3, 2366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &miss); 2367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); 2369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 2370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); 2373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23765913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* StoreStubCompiler::CompileStoreCallback(JSObject* object, 23775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck AccessorInfo* callback, 23785913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck String* name) { 2379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : value 2381402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- r1 : receiver 2382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 2383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object isn't a smi. 2388402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ tst(r1, Operand(kSmiTagMask)); 2389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &miss); 2390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the object hasn't changed. 2392402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); 2393402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(r3, Operand(Handle<Map>(object->map()))); 2394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 2395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform global security token check if needed. 2397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsJSGlobalProxy()) { 2398402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CheckAccessGlobalProxy(r1, r3, &miss); 2399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stub never generated for non-global objects that require access 2402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks. 2403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 2404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2405402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(r1); // receiver 2406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback info 24076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Push(ip, r2, r0); 2408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to the runtime system. 2410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference store_callback_property = 2411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference(IC_Utility(IC::kStoreCallbackProperty)); 24126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(store_callback_property, 4, 1); 2413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); 2417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 2418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24245913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, 24255913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck String* name) { 2426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : value 2428402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- r1 : receiver 2429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 2430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object isn't a smi. 2435402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ tst(r1, Operand(kSmiTagMask)); 2436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &miss); 2437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the object hasn't changed. 2439402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); 2440402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(r3, Operand(Handle<Map>(receiver->map()))); 2441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 2442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform global security token check if needed. 2444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (receiver->IsJSGlobalProxy()) { 2445402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CheckAccessGlobalProxy(r1, r3, &miss); 2446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2448402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Stub is never generated for non-global objects that require access 2449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks. 2450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); 2451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Push(r1, r2, r0); // Receiver, name, value. 2453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to the runtime system. 2455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference store_ic_property = 2456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference(IC_Utility(IC::kStoreInterceptorProperty)); 24576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(store_ic_property, 3, 1); 2458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); 2462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 2463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24695913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, 24705913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSGlobalPropertyCell* cell, 24715913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck String* name) { 2472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : value 2474402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- r1 : receiver 2475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 2476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the global has not changed. 2481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); 2482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r3, Operand(Handle<Map>(object->map()))); 2483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 2484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Store the value in the cell. 2486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, Operand(Handle<JSGlobalPropertyCell>(cell))); 2487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r0, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset)); 2488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2489402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ IncrementCounter(&Counters::named_store_global_inline, 1, r4, r3); 2490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Ret(); 2491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2494402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ IncrementCounter(&Counters::named_store_global_inline_miss, 1, r4, r3); 2495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); 2496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 2497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(NORMAL, name); 2500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25035913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, 25045913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSObject* object, 25055913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSObject* last) { 25066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 2507f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -- r0 : receiver 25086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- lr : return address 25096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 25106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss; 25116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 25126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that receiver is not a smi. 25136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ tst(r0, Operand(kSmiTagMask)); 25146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ b(eq, &miss); 25156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 25166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check the maps of the full prototype chain. 25173bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CheckPrototypes(object, r0, last, r3, r1, r4, name, &miss); 25186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 25196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // If the last object in the prototype chain is a global object, 25206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // check that the global property cell is empty. 25216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (last->IsGlobalObject()) { 25225913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck MaybeObject* cell = GenerateCheckPropertyCell(masm(), 25235913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck GlobalObject::cast(last), 25245913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck name, 25255913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck r1, 25265913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck &miss); 25270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (cell->IsFailure()) { 25280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen miss.Unuse(); 25290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen return cell; 25300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 25316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 25326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 25336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return undefined if maps of the full prototype chain are still the 25346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // same and no global property with this name contains a value. 25356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 25366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Ret(); 25376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 25386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss); 25396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 25406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 25416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return the generated code. 25426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return GetCode(NONEXISTENT, Heap::empty_string()); 25436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 25446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 25456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 25465913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* LoadStubCompiler::CompileLoadField(JSObject* object, 25475913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSObject* holder, 25485913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index, 25495913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck String* name) { 2550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -- r0 : receiver 2552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 2553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25573bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch GenerateLoadField(object, holder, r0, r3, r1, r4, index, name, &miss); 2558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(FIELD, name); 2563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25665913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* LoadStubCompiler::CompileLoadCallback(String* name, 25675913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSObject* object, 25685913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSObject* holder, 25695913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck AccessorInfo* callback) { 2570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2571f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -- r0 : receiver 2572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 2573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2577e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Failure* failure = Failure::InternalError(); 25783bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch bool success = GenerateLoadCallback(object, holder, r0, r2, r3, r1, r4, 2579e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke callback, name, &miss, &failure); 25800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!success) { 25810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen miss.Unuse(); 25820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen return failure; 25830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 2584e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25935913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* LoadStubCompiler::CompileLoadConstant(JSObject* object, 25945913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSObject* holder, 25955913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* value, 25965913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck String* name) { 2597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -- r0 : receiver 2599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 2600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 26043bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch GenerateLoadConstant(object, holder, r0, r3, r1, r4, value, name, &miss); 2605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CONSTANT_FUNCTION, name); 2610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 26135913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* object, 26145913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSObject* holder, 26155913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck String* name) { 2616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2617f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -- r0 : receiver 2618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 2619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupResult lookup; 26244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke LookupPostInterceptor(holder, name, &lookup); 2625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadInterceptor(object, 2626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block holder, 2627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &lookup, 2628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r0, 2629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r2, 2630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r3, 2631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r1, 26323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch r4, 2633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block name, 2634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &miss); 2635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 26435913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* LoadStubCompiler::CompileLoadGlobal(JSObject* object, 26445913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck GlobalObject* holder, 26455913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSGlobalPropertyCell* cell, 26465913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck String* name, 26475913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck bool is_dont_delete) { 2648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2649f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -- r0 : receiver 2650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 2651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the object is the holder then we know that it's a global 2656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object which can only happen for contextual calls. In this case, 2657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the receiver cannot be a smi. 2658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object != holder) { 26596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ tst(r0, Operand(kSmiTagMask)); 2660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &miss); 2661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the global has not changed. 26643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CheckPrototypes(object, r0, holder, r3, r4, r1, name, &miss); 2665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the value from the cell. 2667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); 26686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ldr(r4, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); 2669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for deleted property if property can actually be deleted. 2671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!is_dont_delete) { 2672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 26736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(r4, ip); 2674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &miss); 2675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 26776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r0, r4); 26780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ IncrementCounter(&Counters::named_load_global_stub, 1, r1, r3); 2679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Ret(); 2680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 26820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ IncrementCounter(&Counters::named_load_global_stub_miss, 1, r1, r3); 2683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(NORMAL, name); 2687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 26905913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* KeyedLoadStubCompiler::CompileLoadField(String* name, 26915913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSObject* receiver, 26925913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSObject* holder, 26935913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index) { 2694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 26966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- r0 : key 269725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // -- r1 : receiver 2698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check the key is the cached one. 27026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(r0, Operand(Handle<String>(name))); 2703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 2704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27053bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch GenerateLoadField(receiver, holder, r1, r2, r3, r4, index, name, &miss); 2706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(FIELD, name); 2710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27135913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* KeyedLoadStubCompiler::CompileLoadCallback( 27145913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck String* name, 27155913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSObject* receiver, 27165913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSObject* holder, 27175913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck AccessorInfo* callback) { 2718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 27206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- r0 : key 272125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // -- r1 : receiver 2722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check the key is the cached one. 27266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(r0, Operand(Handle<String>(name))); 2727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 2728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2729e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Failure* failure = Failure::InternalError(); 27303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch bool success = GenerateLoadCallback(receiver, holder, r1, r0, r2, r3, r4, 2731e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke callback, name, &miss, &failure); 27320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!success) { 27330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen miss.Unuse(); 27340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen return failure; 27350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 2736e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27445913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* KeyedLoadStubCompiler::CompileLoadConstant(String* name, 27455913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSObject* receiver, 27465913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSObject* holder, 27475913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* value) { 2748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 27506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- r0 : key 275125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // -- r1 : receiver 2752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check the key is the cached one. 27566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(r0, Operand(Handle<String>(name))); 2757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 2758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27593bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch GenerateLoadConstant(receiver, holder, r1, r2, r3, r4, value, name, &miss); 2760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CONSTANT_FUNCTION, name); 2765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27685913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, 27695913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSObject* holder, 27705913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck String* name) { 2771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 27736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- r0 : key 277425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // -- r1 : receiver 2775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check the key is the cached one. 27796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(r0, Operand(Handle<String>(name))); 2780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 2781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupResult lookup; 27834515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke LookupPostInterceptor(holder, name, &lookup); 2784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadInterceptor(receiver, 2785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block holder, 2786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &lookup, 27876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block r1, 2788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r0, 2789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r2, 2790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r3, 27913bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch r4, 2792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block name, 2793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &miss); 2794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28015913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) { 2802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 28046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- r0 : key 280525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // -- r1 : receiver 2806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check the key is the cached one. 28106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(r0, Operand(Handle<String>(name))); 2811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 2812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GenerateLoadArrayLength(masm(), r1, r2, &miss); 2814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28215913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { 2822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 28246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- r0 : key 282525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // -- r1 : receiver 2826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 28288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ IncrementCounter(&Counters::keyed_load_string_length, 1, r2, r3); 2829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check the key is the cached one. 28316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(r0, Operand(Handle<String>(name))); 2832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 2833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GenerateLoadStringLength(masm(), r1, r2, r3, &miss); 2835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 28368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ DecrementCounter(&Counters::keyed_load_string_length, 1, r2, r3); 2837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28445913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { 2845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 28476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- r0 : key 284825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // -- r1 : receiver 2849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 28508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label miss; 28518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 28528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ IncrementCounter(&Counters::keyed_load_function_prototype, 1, r2, r3); 28538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 28548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check the name hasn't changed. 28558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ cmp(r0, Operand(Handle<String>(name))); 28568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(ne, &miss); 28578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 28588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GenerateLoadFunctionPrototype(masm(), r1, r2, r3, &miss); 28598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&miss); 28608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ DecrementCounter(&Counters::keyed_load_function_prototype, 1, r2, r3); 2861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28675913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, 28685913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index, 28695913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Map* transition, 28705913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck String* name) { 2871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : value 2873f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -- r1 : key 2874f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -- r2 : receiver 2875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2879f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ IncrementCounter(&Counters::keyed_store_field, 1, r3, r4); 2880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 2882f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ cmp(r1, Operand(Handle<String>(name))); 2883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 2884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2885f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // r3 is used as scratch register. r1 and r2 keep their values if a jump to 2886f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // the miss label is generated. 2887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateStoreField(masm(), 2888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block object, 2889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block index, 2890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block transition, 2891f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke r2, r1, r3, 2892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &miss); 2893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2895f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ DecrementCounter(&Counters::keyed_store_field, 1, r3, r4); 2896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss)); 2897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 2899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); 2902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) WangMaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { 2906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : argc 2908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r1 : constructor 2909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- [sp] : last argument 2911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label generic_stub_call; 2913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use r7 for holding undefined which is used in several places below. 2915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(r7, Heap::kUndefinedValueRootIndex); 2916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 2918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check to see whether there are any break points in the function code. If 2919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // there are jump to the generic constructor stub which calls the actual 2920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // code for the function thereby hitting the break points. 2921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 2922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kDebugInfoOffset)); 2923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, r7); 2924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &generic_stub_call); 2925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 2926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the initial map and verify that it is in fact a map. 2928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 2929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 2930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 2931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r2, Operand(kSmiTagMask)); 2932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &generic_stub_call); 2933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(r2, r3, r4, MAP_TYPE); 2934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &generic_stub_call); 2935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 2937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cannot construct functions this way. 2938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 2939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 2940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: initial map 2941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 2942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE); 2943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Check(ne, "Function constructed by construct stub."); 2944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 2945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Now allocate the JSObject in new space. 2947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 2948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 2949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: initial map 2950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 2951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset)); 2952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ AllocateInNewSpace(r3, 2953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r4, 2954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r5, 2955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r6, 2956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &generic_stub_call, 295725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen SIZE_IN_WORDS); 2958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocated the JSObject, now initialize the fields. Map is set to initial 2960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // map and properties and elements are set to empty fixed array. 2961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 2962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 2963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: initial map 2964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: object size (in words) 2965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject (not tagged) 2966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 2967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex); 2968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r5, r4); 2969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); 2970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r2, MemOperand(r5, kPointerSize, PostIndex)); 2971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset); 2972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); 2973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset); 2974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); 2975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the location of the first argument. The stack contains only the 2977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // argc arguments. 2978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r1, sp, Operand(r0, LSL, kPointerSizeLog2)); 2979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill all the in-object properties with undefined. 2981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 2982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: first argument 2983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: object size (in words) 2984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject (not tagged) 2985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r5: First in-object property of JSObject (not tagged) 2986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 2987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the initialized properties with a constant value or a passed argument 2988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // depending on the this.x = ...; assignment in the function. 29898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang SharedFunctionInfo* shared = function->shared(); 2990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < shared->this_property_assignments_count(); i++) { 2991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (shared->IsThisPropertyAssignmentArgument(i)) { 2992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label not_passed, next; 2993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the argument assigned to the property is actually passed. 2994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int arg_number = shared->GetThisPropertyAssignmentArgument(i); 2995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, Operand(arg_number)); 2996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(le, ¬_passed); 2997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Argument passed - find it on the stack. 2998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, MemOperand(r1, (arg_number + 1) * -kPointerSize)); 2999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r2, MemOperand(r5, kPointerSize, PostIndex)); 3000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(&next); 3001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(¬_passed); 3002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the property to undefined. 3003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r7, MemOperand(r5, kPointerSize, PostIndex)); 3004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&next); 3005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 3006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the property to the constant value. 3007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i)); 3008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, Operand(constant)); 3009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r2, MemOperand(r5, kPointerSize, PostIndex)); 3010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the unused in-object property fields with undefined. 30148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ASSERT(function->has_initial_map()); 3015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = shared->this_property_assignments_count(); 30168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang i < function->initial_map()->inobject_properties(); 3017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i++) { 3018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r7, MemOperand(r5, kPointerSize, PostIndex)); 3019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 3022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject (not tagged) 3023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move argc to r1 and the JSObject to return to r0 and tag it. 3024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r1, r0); 3025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, r4); 3026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ orr(r0, r0, Operand(kHeapObjectTag)); 3027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: JSObject 3029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: argc 3030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Remove caller arguments and receiver from the stack and return. 3031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2)); 3032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(kPointerSize)); 3033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::constructed_objects, 1, r1, r2); 3034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::constructed_objects_stub, 1, r1, r2); 3035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 3036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the generic stub in case the specialized code cannot handle the 3038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // construction. 3039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&generic_stub_call); 3040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric); 3041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> generic_construct_stub(code); 3042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); 3043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 3045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(); 3046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 3050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 3052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3053f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_ARM 3054