13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h" 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_ARM) 31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "ic-inl.h" 338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "codegen.h" 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "stub-cache.h" 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm) 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic void ProbeTable(Isolate* isolate, 4344f0eee88ff00398ff7f715fab053374d808c90dSteve Block MacroAssembler* masm, 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Flags flags, 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StubCache::Table table, 463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver, 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register name, 483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Number of the cache entry, not scaled. 493e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu Register offset, 503e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu Register scratch, 513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch2, 523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register offset_scratch) { 5344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference key_offset(isolate->stub_cache()->key_reference(table)); 5444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference value_offset(isolate->stub_cache()->value_reference(table)); 553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference map_offset(isolate->stub_cache()->map_reference(table)); 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 573e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu uint32_t key_off_addr = reinterpret_cast<uint32_t>(key_offset.address()); 583e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu uint32_t value_off_addr = reinterpret_cast<uint32_t>(value_offset.address()); 593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uint32_t map_off_addr = reinterpret_cast<uint32_t>(map_offset.address()); 603e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 613e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Check the relative positions of the address fields. 623e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(value_off_addr > key_off_addr); 633e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT((value_off_addr - key_off_addr) % 4 == 0); 643e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT((value_off_addr - key_off_addr) < (256 * 4)); 653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(map_off_addr > key_off_addr); 663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT((map_off_addr - key_off_addr) % 4 == 0); 673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT((map_off_addr - key_off_addr) < (256 * 4)); 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 693e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu Label miss; 703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register base_addr = scratch; 713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch = no_reg; 723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Multiply by 3 because there are 3 fields per entry (name, code, map). 743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(offset_scratch, offset, Operand(offset, LSL, 1)); 753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Calculate the base address of the entry. 773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(base_addr, Operand(key_offset)); 783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(base_addr, base_addr, Operand(offset_scratch, LSL, kPointerSizeLog2)); 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the key in the entry matches the name. 813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(ip, MemOperand(base_addr, 0)); 826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(name, ip); 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check the map matches. 863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(ip, MemOperand(base_addr, map_off_addr - key_off_addr)); 873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(scratch2, FieldMemOperand(receiver, HeapObject::kMapOffset)); 883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(ip, scratch2); 893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &miss); 903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the code entry from the cache. 923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register code = scratch2; 933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch2 = no_reg; 943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(code, MemOperand(base_addr, value_off_addr - key_off_addr)); 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the flags match what we're looking for. 973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register flags_reg = base_addr; 983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch base_addr = no_reg; 993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(flags_reg, FieldMemOperand(code, Code::kFlagsOffset)); 1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // It's a nice optimization if this constant is encodable in the bic insn. 1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uint32_t mask = Code::kFlagsNotUsedInLookup; 1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(__ ImmediateFitsAddrMode1Instruction(mask)); 1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bic(flags_reg, flags_reg, Operand(mask)); 1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Using cmn and the negative instead of cmp means we can use movw. 1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (flags < 0) { 1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmn(flags_reg, Operand(-flags)); 1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(flags_reg, Operand(flags)); 1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG 1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) { 1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&miss); 1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) { 1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&miss); 1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the first instruction in the code stub. 1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(pc, code, Operand(Code::kHeaderSize - kHeapObjectTag)); 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1243e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Miss: fall through. 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// Helper function used to check that the dictionary doesn't contain 1303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// the property. This function may return false negatives, so miss_label 1313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// must always call a backup property check that is complete. 1323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// This function is safe to call if the receiver has fast properties. 1333bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// Name must be a symbol and receiver must be a heap object. 1343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateDictionaryNegativeLookup(MacroAssembler* masm, 1353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss_label, 1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver, 1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 1383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch0, 1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1) { 1403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(name->IsSymbol()); 14144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = masm->isolate()->counters(); 14244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); 14344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); 1443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1453bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label done; 1463bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1473bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const int kInterceptorOrAccessCheckNeededMask = 1483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); 1493bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1503bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Bail out if the receiver has a named interceptor or requires access checks. 1513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register map = scratch1; 1523bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); 1533bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ ldrb(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); 1543bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ tst(scratch0, Operand(kInterceptorOrAccessCheckNeededMask)); 1553bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ b(ne, miss_label); 1563bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1573bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Check that receiver is a JSObject. 1583bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ ldrb(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); 1593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp(scratch0, Operand(FIRST_SPEC_OBJECT_TYPE)); 1603bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ b(lt, miss_label); 1613bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1623bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Load properties array. 1633bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register properties = scratch0; 1643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 1653bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Check that the properties array is a dictionary. 1663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ ldr(map, FieldMemOperand(properties, HeapObject::kMapOffset)); 1673bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register tmp = properties; 1683bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); 1693bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ cmp(map, tmp); 1703bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ b(ne, miss_label); 1713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Restore the temporarily used register. 1733bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 1743bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringDictionaryLookupStub::GenerateNegativeLookup(masm, 1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch miss_label, 1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &done, 1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver, 1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch properties, 1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, 1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1); 1833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ bind(&done); 18444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); 1853bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch} 1863bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1873bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCache::GenerateProbe(MacroAssembler* masm, 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Flags flags, 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register name, 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 1933e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu Register extra, 1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register extra2, 1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register extra3) { 19644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate = masm->isolate(); 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure that code is valid. The multiplying code relies on the 2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // entry size being 12. 2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(sizeof(Entry) == 12); 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure the flags does not name a specific type. 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(Code::ExtractTypeFromFlags(flags) == 0); 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure that there are no register conflicts. 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!scratch.is(receiver)); 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!scratch.is(name)); 2093e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(!extra.is(receiver)); 2103e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(!extra.is(name)); 2113e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(!extra.is(scratch)); 2123e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(!extra2.is(receiver)); 2133e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(!extra2.is(name)); 2143e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(!extra2.is(scratch)); 2153e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(!extra2.is(extra)); 2163e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 2173e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Check scratch, extra and extra2 registers are valid. 2183e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(!scratch.is(no_reg)); 2193e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(!extra.is(no_reg)); 2203e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(!extra2.is(no_reg)); 2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!extra3.is(no_reg)); 2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Counters* counters = masm->isolate()->counters(); 2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1, 2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch extra2, extra3); 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 2283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(receiver, &miss); 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the map of the receiver and compute the hash. 231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(scratch, FieldMemOperand(name, String::kHashFieldOffset)); 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(ip, FieldMemOperand(receiver, HeapObject::kMapOffset)); 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(scratch, scratch, Operand(ip)); 2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uint32_t mask = kPrimaryTableSize - 1; 2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We shift out the last two bits because they are not part of the hash and 2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // they are always 01 for maps. 2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(scratch, Operand(scratch, LSR, kHeapObjectTagSize)); 2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Mask down the eor argument to the minimum to keep the immediate 2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ARM-encodable. 2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ eor(scratch, scratch, Operand((flags >> kHeapObjectTagSize) & mask)); 2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Prefer and_ to ubfx here because ubfx takes 2 cycles. 2423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ and_(scratch, scratch, Operand(mask)); 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the primary table. 2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ProbeTable(isolate, 2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm, 2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch flags, 2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kPrimary, 2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver, 2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, 2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch extra, 2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch extra2, 2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch extra3); 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Primary miss: Compute hash for secondary probe. 2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(scratch, scratch, Operand(name, LSR, kHeapObjectTagSize)); 2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uint32_t mask2 = kSecondaryTableSize - 1; 2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(scratch, scratch, Operand((flags >> kHeapObjectTagSize) & mask2)); 2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ and_(scratch, scratch, Operand(mask2)); 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the secondary table. 2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ProbeTable(isolate, 2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm, 2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch flags, 2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kSecondary, 2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver, 2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, 2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch extra, 2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch extra2, 2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch extra3); 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cache miss: Fall-through and let caller handle the miss by 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // entering the runtime system. 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1, 2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch extra2, extra3); 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index, 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register prototype) { 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the global or builtins object from the current context. 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the global context from the global or builtins object. 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(prototype, 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldMemOperand(prototype, GlobalObject::kGlobalContextOffset)); 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the function from the global context. 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(prototype, MemOperand(prototype, Context::SlotOffset(index))); 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the initial map. The global functions all have initial maps. 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(prototype, 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldMemOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset)); 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the prototype from the initial map. 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( 3013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler* masm, 3023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int index, 3033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register prototype, 3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 30544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate = masm->isolate(); 3060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Check we're still in the same context. 3070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ ldr(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); 30844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Move(ip, isolate->global()); 3090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ cmp(prototype, ip); 3100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ b(ne, miss); 3117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Get the global function with the given index. 3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function( 3133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JSFunction::cast(isolate->global_context()->get(index))); 3147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Load its initial map. The global functions all have initial maps. 3157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Move(prototype, Handle<Map>(function->initial_map())); 3167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Load the prototype from the initial map. 3177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); 3187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 3197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 3207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Load a fast property out of a holder object (src). In-object properties 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// are loaded directly otherwise the property is loaded from the properties 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// fixed array. 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, 3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register dst, 3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register src, 3273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 3283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int index) { 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust for the number of properties stored in the holder. 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block index -= holder->map()->inobject_properties(); 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (index < 0) { 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the property straight out of the holder. 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = holder->map()->instance_size() + (index * kPointerSize); 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(dst, FieldMemOperand(src, offset)); 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the offset into the properties array. 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = index * kPointerSize + FixedArray::kHeaderSize; 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(dst, FieldMemOperand(src, JSObject::kPropertiesOffset)); 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(dst, FieldMemOperand(dst, offset)); 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss_label) { 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 3493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(receiver, miss_label); 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is a JS array. 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE); 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, miss_label); 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load length directly from the JS array. 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Ret(); 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 361402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// Generate code to check if an object is a string. If the object is a 362402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// heap object, its map's instance type is left in the scratch1 register. 363402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// If this is not needed, scratch1 and scratch2 may be the same register. 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GenerateStringCheck(MacroAssembler* masm, 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* smi, 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* non_string_object) { 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 3713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(receiver, smi); 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is a string. 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset)); 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(scratch2, scratch1, Operand(kIsNotStringMask)); 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The cast is to resolve the overload for the argument of 0x0. 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag))); 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, non_string_object); 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate code to load the length from a string object and return the length. 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// If the receiver object is not a string or a wrapped string object the 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// execution continues at the miss label. The register containing the 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// receiver is potentially clobbered. 387402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, 388402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register receiver, 389402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register scratch1, 390402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register scratch2, 3911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* miss, 3921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool support_wrappers) { 393402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label check_wrapper; 394402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the object is a string leaving the instance type in the 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch1 register. 3971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block GenerateStringCheck(masm, receiver, scratch1, scratch2, miss, 3981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block support_wrappers ? &check_wrapper : miss); 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load length directly from the string. 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, FieldMemOperand(receiver, String::kLengthOffset)); 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Ret(); 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (support_wrappers) { 4051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check if the object is a JSValue wrapper. 4061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&check_wrapper); 4071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmp(scratch1, Operand(JS_VALUE_TYPE)); 4081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(ne, miss); 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Unwrap the value and check if the wrapped value is a string. 4111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldr(scratch1, FieldMemOperand(receiver, JSValue::kValueOffset)); 4121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block GenerateStringCheck(masm, scratch1, scratch2, scratch2, miss, miss); 4131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldr(r0, FieldMemOperand(scratch1, String::kLengthOffset)); 4141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(); 4151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss_label) { 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, scratch1); 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Ret(); 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate StoreField code, value is passed in r0 register. 431402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// When leaving generated code after success, the receiver_reg and name_reg 432402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// may be clobbered. Upon branch to miss_label, the receiver and name 433402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// registers have their original values. 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateStoreField(MacroAssembler* masm, 4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index, 4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> transition, 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver_reg, 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register name_reg, 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss_label) { 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0 : value 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label exit; 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that the map of the object hasn't changed. 4468f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS 4478f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch : REQUIRE_EXACT_MAP; 4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(receiver_reg, scratch, Handle<Map>(object->map()), miss_label, 4498f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch DO_SMI_CHECK, mode); 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform global security token check if needed. 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsJSGlobalProxy()) { 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stub never generated for non-global objects that require access 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks. 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform map transition for the receiver if necessary. 4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) { 462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The properties must be extended before we can store the value. 463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We jump to a runtime call that extends the properties array. 464402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(receiver_reg); 4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r2, Operand(transition)); 4666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Push(r2, r0); 4676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference( 46844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), 46944f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm->isolate()), 47044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3, 47144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1); 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!transition.is_null()) { 476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update the map of the object; no write barrier updating is 477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // needed because the map is never in new space. 4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ip, Operand(transition)); 479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(ip, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust for the number of properties stored in the object. Even in the 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // face of a transition we can use the old map here because the size of the 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object and the number of in-object properties is not going to change. 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block index -= object->map()->inobject_properties(); 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (index < 0) { 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the property straight into the object. 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = object->map()->instance_size() + (index * kPointerSize); 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r0, FieldMemOperand(receiver_reg, offset)); 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Skip updating write barrier if storing a smi. 4933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(r0, &exit); 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update the write barrier for the array address. 4969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Pass the now unused name_reg as a scratch register. 4973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(name_reg, r0); 4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(receiver_reg, 4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch offset, 5003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name_reg, 5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kLRHasNotBeenSaved, 5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs); 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Write to the properties array. 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = index * kPointerSize + FixedArray::kHeaderSize; 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the properties array 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(scratch, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r0, FieldMemOperand(scratch, offset)); 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Skip updating write barrier if storing a smi. 5123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(r0, &exit); 513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update the write barrier for the array address. 515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Ok to clobber receiver_reg and name_reg, since we return. 5163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(name_reg, r0); 5173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(scratch, 5183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch offset, 5193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name_reg, 5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver_reg, 5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kLRHasNotBeenSaved, 5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs); 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the value (register r0). 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&exit); 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Ret(); 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); 5333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = (kind == Code::LOAD_IC) 5343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? masm->isolate()->builtins()->LoadIC_Miss() 5353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : masm->isolate()->builtins()->KeyedLoadIC_Miss(); 5363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(code, RelocInfo::CODE_TARGET); 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkestatic void GenerateCallFunction(MacroAssembler* masm, 5413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 5424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke const ParameterCount& arguments, 543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* miss, 544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Code::ExtraICState extra_ic_state) { 5454515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // ----------- S t a t e ------------- 5464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- r0: receiver 5474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- r1: function to call 5484515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // ----------------------------------- 5494515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 5504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Check that the function really is a function. 5511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r1, miss); 552402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); 5534515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ b(ne, miss); 5544515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 5554515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Patch the receiver on the stack with the global proxy if 5564515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // necessary. 5574515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (object->IsGlobalObject()) { 5584515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); 5594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ str(r3, MemOperand(sp, arguments.immediate() * kPointerSize)); 5604515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 5614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 5624515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Invoke the function. 563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state) 564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(r1, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind); 5674515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke} 5684515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 5694515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 5704515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkestatic void PushInterceptorArguments(MacroAssembler* masm, 5714515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Register receiver, 5724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Register holder, 5734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke Register name, 5743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder_obj) { 5754515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(name); 5763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); 5773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); 5786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch = name; 5793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(scratch, Operand(interceptor)); 5804515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(scratch); 5816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(receiver); 5826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(holder); 5834515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ ldr(scratch, FieldMemOperand(scratch, InterceptorInfo::kDataOffset)); 5844515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(scratch); 5854515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke} 5864515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 5874515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 5883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void CompileCallLoadPropertyWithInterceptor( 5893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler* masm, 5903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver, 5913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register holder, 5923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register name, 5933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder_obj) { 5944515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke PushInterceptorArguments(masm, receiver, holder, name, holder_obj); 5954515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 5964515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke ExternalReference ref = 59744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), 59844f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm->isolate()); 5994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mov(r0, Operand(5)); 6004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ mov(r1, Operand(ref)); 6014515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 6024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke CEntryStub stub(1); 6034515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallStub(&stub); 6044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke} 6054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 6063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockstatic const int kFastApiCallArguments = 3; 6084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 6096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Reserves space for the extra arguments to FastHandleApiCall in the 6106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// caller's frame. 6116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// 6121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// These arguments are set by CheckPrototypes and GenerateFastApiDirectCall. 6136ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void ReserveSpaceForFastApiCall(MacroAssembler* masm, 6146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch) { 6156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(scratch, Operand(Smi::FromInt(0))); 6161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (int i = 0; i < kFastApiCallArguments; i++) { 6171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(scratch); 6181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 6196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 6206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Undoes the effects of ReserveSpaceForFastApiCall. 6236ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void FreeSpaceForFastApiCall(MacroAssembler* masm) { 6241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Drop(kFastApiCallArguments); 6256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 6266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateFastApiDirectCall(MacroAssembler* masm, 6291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block const CallOptimization& optimization, 6301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int argc) { 6311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------- S t a t e ------------- 6321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- sp[0] : holder (set by CheckPrototypes) 6333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- sp[4] : callee JS function 6341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- sp[8] : call data 6353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- sp[12] : last JS argument 6361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- ... 6373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- sp[(argc + 3) * 4] : first JS argument 6381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- sp[(argc + 4) * 4] : receiver 6391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 6406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the function and setup the context. 6413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function = optimization.constant_function(); 6423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(r5, function); 6438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(cp, FieldMemOperand(r5, JSFunction::kContextOffset)); 6446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Pass the additional arguments FastHandleApiCall expects. 6463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 6473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> call_data(api_call_info->data()); 6483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (masm->isolate()->heap()->InNewSpace(*call_data)) { 6493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(r0, api_call_info); 6508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r6, FieldMemOperand(r0, CallHandlerInfo::kDataOffset)); 6516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 6523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(r6, call_data); 6536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 6543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store JS function and call data. 6551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ stm(ib, sp, r5.bit() | r6.bit()); 6566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // r2 points to call data as expected by Arguments 6581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // (refer to layout above). 6591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ add(r2, sp, Operand(2 * kPointerSize)); 6606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 66185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch const int kApiStackSpace = 4; 6623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope frame_scope(masm, StackFrame::MANUAL); 6641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ EnterExitFrame(false, kApiStackSpace); 6651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 6661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // r0 = v8::Arguments& 6671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Arguments is after the return address. 6681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ add(r0, sp, Operand(1 * kPointerSize)); 6691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // v8::Arguments::implicit_args = data 6701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ str(r2, MemOperand(r0, 0 * kPointerSize)); 6711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // v8::Arguments::values = last argument 6721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ add(ip, r2, Operand(argc * kPointerSize)); 6731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ str(ip, MemOperand(r0, 1 * kPointerSize)); 6741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // v8::Arguments::length_ = argc 6751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(ip, Operand(argc)); 6761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ str(ip, MemOperand(r0, 2 * kPointerSize)); 6771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // v8::Arguments::is_construct_call = 0 6781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(ip, Operand(0)); 6791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ str(ip, MemOperand(r0, 3 * kPointerSize)); 6801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 681e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch const int kStackUnwindSpace = argc + kFastApiCallArguments + 1; 6823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Address function_address = v8::ToCData<Address>(api_call_info->callback()); 6833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ApiFunction fun(function_address); 68444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference ref = ExternalReference(&fun, 68544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::DIRECT_API_CALL, 68644f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm->isolate()); 6873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AllowExternalCallThatCantCauseGC scope(masm); 6883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallApiFunctionAndReturn(ref, kStackUnwindSpace); 6906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 6916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6936ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass CallInterceptorCompiler BASE_EMBEDDED { 6946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public: 6956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CallInterceptorCompiler(StubCompiler* stub_compiler, 6966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const ParameterCount& arguments, 697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register name, 698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Code::ExtraICState extra_ic_state) 6996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block : stub_compiler_(stub_compiler), 7006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block arguments_(arguments), 701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch name_(name), 702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch extra_ic_state_(extra_ic_state) {} 7036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 7043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void Compile(MacroAssembler* masm, 7053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 7063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 7073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 7083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult* lookup, 7093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver, 7103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 7113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch2, 7123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch3, 7133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 7146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(holder->HasNamedInterceptor()); 7156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); 7166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 7176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the receiver isn't a smi. 7181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(receiver, miss); 7196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CallOptimization optimization(lookup); 7206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (optimization.is_constant_call()) { 7213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3, 7223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch holder, lookup, name, optimization, miss); 7236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 7243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3, 7253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, holder, miss); 7266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 7276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 7286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 7296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private: 7303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CompileCacheable(MacroAssembler* masm, 7313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 7323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver, 7333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 7343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch2, 7353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch3, 7363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> interceptor_holder, 7373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult* lookup, 7383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 7393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const CallOptimization& optimization, 7403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss_label) { 7416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(optimization.is_constant_call()); 7426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(!lookup->holder()->IsGlobalObject()); 74344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = masm->isolate()->counters(); 7446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int depth1 = kInvalidProtoDepth; 7456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int depth2 = kInvalidProtoDepth; 7466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bool can_do_fast_api_call = false; 7476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (optimization.is_simple_api_call() && 7483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch !lookup->holder()->IsGlobalObject()) { 7493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch depth1 = optimization.GetPrototypeDepthOfExpectedType( 7503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch object, interceptor_holder); 7513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (depth1 == kInvalidProtoDepth) { 7523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch depth2 = optimization.GetPrototypeDepthOfExpectedType( 7533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch interceptor_holder, Handle<JSObject>(lookup->holder())); 7543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 7553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch can_do_fast_api_call = 7563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth; 7576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 7586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 75944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_const_interceptor(), 1, 7603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, scratch2); 7616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 7626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (can_do_fast_api_call) { 76344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1, 7646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block scratch1, scratch2); 7656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ReserveSpaceForFastApiCall(masm, scratch1); 7666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 7676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check that the maps from receiver to interceptor's holder 769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // haven't changed and thus we can invoke interceptor. 7706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss_cleanup; 7716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; 7726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register holder = 7733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, 7743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, scratch2, scratch3, 7753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, depth1, miss); 7766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invoke an interceptor and if it provides a value, 778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // branch to |regular_invoke|. 7796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label regular_invoke; 780f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2, 7816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ®ular_invoke); 7826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Interceptor returned nothing for this property. Try to use cached 784f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // constant function. 7856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 786f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check that the maps from interceptor's holder to constant function's 787f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // holder haven't changed and thus we can use cached constant function. 7883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (*interceptor_holder != lookup->holder()) { 7897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch stub_compiler_->CheckPrototypes(interceptor_holder, receiver, 7903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(lookup->holder()), 7913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, scratch2, scratch3, 7923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, depth2, miss); 7937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 7947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // CheckPrototypes has a side effect of fetching a 'holder' 7957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // for API (object which is instanceof for the signature). It's 7967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // safe to omit it here, as if present, it should be fetched 7977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // by the previous CheckPrototypes. 7987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(depth2 == kInvalidProtoDepth); 7997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 8006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 801f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invoke function. 8026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (can_do_fast_api_call) { 8033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateFastApiDirectCall(masm, optimization, arguments_.immediate()); 8046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) 806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 8086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ InvokeFunction(optimization.constant_function(), arguments_, 8093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JUMP_FUNCTION, NullCallWrapper(), call_kind); 8106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 8116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Deferred code for fast API call case---clean preallocated space. 8136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (can_do_fast_api_call) { 8146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss_cleanup); 8156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FreeSpaceForFastApiCall(masm); 8166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ b(miss_label); 8176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 8186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 819f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invoke a regular function. 8206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(®ular_invoke); 8216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (can_do_fast_api_call) { 8226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FreeSpaceForFastApiCall(masm); 8236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 8246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 8256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void CompileRegular(MacroAssembler* masm, 8273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 8286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register receiver, 8296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch1, 8306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch2, 8313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 8323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 8333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> interceptor_holder, 8346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* miss_label) { 8356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register holder = 836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, 8373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, scratch2, scratch3, 8383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, miss_label); 8396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Call a runtime function to load the interceptor property. 8413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 8426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Save the name_ register across the call. 8436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(name_); 8443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder); 8456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CallExternalReference( 84644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), 84744f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm->isolate()), 84844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 5); 8496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Restore the name_ register. 8506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(name_); 8513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Leave the internal frame. 8526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 8536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void LoadWithInterceptor(MacroAssembler* masm, 8556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register receiver, 8566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register holder, 8573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder_obj, 8586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch, 8596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* interceptor_succeeded) { 8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 8623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(holder, name_); 8633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompileCallLoadPropertyWithInterceptor(masm, 8643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver, 8653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch holder, 8663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name_, 8673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch holder_obj); 8683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(name_); // Restore the name. 8693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(receiver); // Restore the holder. 8703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 8716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // If interceptor returns no-result sentinel, call the constant function. 8726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); 8736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(r0, scratch); 8746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ b(ne, interceptor_succeeded); 8756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 8766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block StubCompiler* stub_compiler_; 8786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const ParameterCount& arguments_; 8796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register name_; 880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Code::ExtraICState extra_ic_state_; 8816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}; 8826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Generate code to check that a global property cell is empty. Create 8856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// the property cell at compilation time if no cell exists for the 8866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// property. 8873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateCheckPropertyCell(MacroAssembler* masm, 8883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject> global, 8893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 8903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 8913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 8923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell = 8933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GlobalObject::EnsurePropertyCell(global, name); 8946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(cell->value()->IsTheHole()); 8953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(scratch, Operand(cell)); 8966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ldr(scratch, 8976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); 8986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 8996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(scratch, ip); 9006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ b(ne, miss); 9016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 9026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Calls GenerateCheckPropertyCell for each global object in the prototype chain 905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// from object to (but not including) holder. 9063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateCheckPropertyCells(MacroAssembler* masm, 9073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 9083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 9093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 9103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 9113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 9123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> current = object; 9133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch while (!current.is_identical_to(holder)) { 914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (current->IsGlobalObject()) { 9153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateCheckPropertyCell(masm, 9163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject>::cast(current), 9173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, 9183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 9193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch miss); 920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 9213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); 922b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 9261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Convert and store int passed in register ival to IEEE 754 single precision 9271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// floating point value at memory location (dst + 4 * wordoffset) 9281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// If VFP3 is available use it for conversion. 9291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockstatic void StoreIntAsFloat(MacroAssembler* masm, 9301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register dst, 9311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register wordoffset, 9321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register ival, 9331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register fval, 9341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register scratch1, 9351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register scratch2) { 9368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CpuFeatures::IsSupported(VFP3)) { 9371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CpuFeatures::Scope scope(VFP3); 9381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ vmov(s0, ival); 9391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ add(scratch1, dst, Operand(wordoffset, LSL, 2)); 9401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ vcvt_f32_s32(s0, s0); 9411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ vstr(s0, scratch1, 0); 9421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 9431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label not_special, done; 9441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Move sign bit from source to destination. This works because the sign 9451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // bit in the exponent word of the double has the same position and polarity 9461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // as the 2's complement sign bit in a Smi. 9471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(kBinary32SignMask == 0x80000000u); 9481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ and_(fval, ival, Operand(kBinary32SignMask), SetCC); 9501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Negate value if it is negative. 9511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ rsb(ival, ival, Operand(0, RelocInfo::NONE), LeaveCC, ne); 9521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // We have -1, 0 or 1, which we treat specially. Register ival contains 9541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // absolute value: it is either equal to 1 (special case of -1 and 1), 9551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // greater than 1 (not a special case) or less than 1 (special case of 0). 9561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmp(ival, Operand(1)); 9571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(gt, ¬_special); 9581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For 1 or -1 we need to or in the 0 exponent (biased). 9601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block static const uint32_t exponent_word_for_1 = 9611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block kBinary32ExponentBias << kBinary32ExponentShift; 9621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ orr(fval, fval, Operand(exponent_word_for_1), LeaveCC, eq); 9641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(&done); 9651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(¬_special); 9671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Count leading zeros. 9681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Gets the wrong answer for 0, but we already checked for that case above. 9691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register zeros = scratch2; 9701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CountLeadingZeros(zeros, ival, scratch1); 9711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Compute exponent and or it into the exponent register. 9731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ rsb(scratch1, 9741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block zeros, 9751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Operand((kBitsPerInt - 1) + kBinary32ExponentBias)); 9761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ orr(fval, 9781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block fval, 9791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Operand(scratch1, LSL, kBinary32ExponentShift)); 9801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Shift up the source chopping the top bit off. 9821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ add(zeros, zeros, Operand(1)); 9831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // This wouldn't work for 1 and -1 as the shift would be 32 which means 0. 9841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(ival, Operand(ival, LSL, zeros)); 9851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // And the top (top 20 bits). 9861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ orr(fval, 9871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block fval, 9881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Operand(ival, LSR, kBitsPerInt - kBinary32MantissaBits)); 9891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&done); 9911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ str(fval, MemOperand(dst, wordoffset, LSL, 2)); 9921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 9931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 9941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Convert unsigned integer with specified number of leading zeroes in binary 9971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// representation to IEEE 754 double. 9981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Integer to convert is passed in register hiword. 9991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Resulting double is returned in registers hiword:loword. 10001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// This functions does not work correctly for 0. 10011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockstatic void GenerateUInt2Double(MacroAssembler* masm, 10021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register hiword, 10031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register loword, 10041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register scratch, 10051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int leading_zeroes) { 10061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block const int meaningful_bits = kBitsPerInt - leading_zeroes - 1; 10071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block const int biased_exponent = HeapNumber::kExponentBias + meaningful_bits; 10081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 10091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block const int mantissa_shift_for_hi_word = 10101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block meaningful_bits - HeapNumber::kMantissaBitsInTopWord; 10111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 10121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block const int mantissa_shift_for_lo_word = 10131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block kBitsPerInt - mantissa_shift_for_hi_word; 10141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 10151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(scratch, Operand(biased_exponent << HeapNumber::kExponentShift)); 10161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (mantissa_shift_for_hi_word > 0) { 10171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(loword, Operand(hiword, LSL, mantissa_shift_for_lo_word)); 10181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ orr(hiword, scratch, Operand(hiword, LSR, mantissa_shift_for_hi_word)); 10191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 10201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(loword, Operand(0, RelocInfo::NONE)); 10211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ orr(hiword, scratch, Operand(hiword, LSL, mantissa_shift_for_hi_word)); 10221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 10231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 10241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // If least significant bit of biased exponent was not 1 it was corrupted 10251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // by most significant bit of mantissa so we should fix that. 10261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (!(biased_exponent & 1)) { 10271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bic(hiword, hiword, Operand(1 << HeapNumber::kExponentShift)); 10281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 10291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 10301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 10316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm()) 1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10363ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochRegister StubCompiler::CheckPrototypes(Handle<JSObject> object, 1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register object_reg, 10383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register holder_reg, 10403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch1, 10413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch2, 10423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 1043402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int save_at_depth, 10443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* miss) { 10453bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Make sure there's no overlap between holder and object registers. 10463bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 10473bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) 10483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch && !scratch2.is(scratch1)); 10493bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 10503bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Keep track of the current object in register reg. 10513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register reg = object_reg; 10523bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch int depth = 0; 10533bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 10543bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch if (save_at_depth == depth) { 10553bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ str(reg, MemOperand(sp)); 10563bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 10573bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 10583bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Check the maps in the prototype chain. 10593bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Traverse the prototype chain from the object and do map checks. 10603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> current = object; 10613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch while (!current.is_identical_to(holder)) { 10623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ++depth; 10633bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 10643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Only global objects and objects that do not require access 10653bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // checks are allowed in stubs. 10663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); 10673bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 10683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> prototype(JSObject::cast(current->GetPrototype())); 10693bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch if (!current->HasFastProperties() && 10703bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch !current->IsJSGlobalObject() && 10713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch !current->IsJSGlobalProxy()) { 10723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch if (!name->IsSymbol()) { 10733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name = factory()->LookupSymbol(name); 10743bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 10753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(current->property_dictionary()->FindEntry(*name) == 10763bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch StringDictionary::kNotFound); 10773bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 10783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateDictionaryNegativeLookup(masm(), miss, reg, name, 10793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, scratch2); 1080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 10813bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); 10823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch reg = holder_reg; // From now on the object will be in holder_reg. 10833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); 10843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 10853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> current_map(current->map()); 10863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK, 10873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ALLOW_ELEMENT_TRANSITION_MAPS); 108885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 10893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check access rights to the global object. This has to happen after 10903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the map check so that we know that the object is actually a global 10913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // object. 10923bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch if (current->IsJSGlobalProxy()) { 10933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckAccessGlobalProxy(reg, scratch2, miss); 10943bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 10953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch reg = holder_reg; // From now on the object will be in holder_reg. 10963bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 10973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (heap()->InNewSpace(*prototype)) { 10983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The prototype is in new space; we cannot store a reference to it 10993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // in the code. Load it from the map. 11003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); 11013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 11023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The prototype is in old space; load it directly. 11033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(reg, Operand(prototype)); 11043bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 11053bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 11063bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 11073bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch if (save_at_depth == depth) { 11083bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ str(reg, MemOperand(sp)); 11093bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 11103bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 11113bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Go to the next object in the prototype chain. 11123bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch current = prototype; 11133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 11143bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1115592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Log the check depth. 1116592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch LOG(masm()->isolate(), IntEvent("check-maps-depth", depth + 1)); 1117592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 11183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check the holder map. 11193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(reg, scratch1, Handle<Map>(current->map()), miss, 11203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); 11213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Perform security check for access to the global object. 1123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); 1124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (holder->IsJSGlobalProxy()) { 11253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ CheckAccessGlobalProxy(reg, scratch1, miss); 11263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 11273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 11283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If we've skipped any global objects, it's not enough to verify that 11293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // their maps haven't changed. We also need to check that the property 11303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // cell for the property is still empty. 11313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); 1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1133402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Return the register containing the holder. 11343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch return reg; 1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadField(Handle<JSObject> object, 11393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 11433bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index, 11453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 11483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(receiver, miss); 1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 11513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register reg = CheckPrototypes( 11523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch object, receiver, holder, scratch1, scratch2, scratch3, name, miss); 1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateFastPropertyLoad(masm(), r0, reg, holder, index); 1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Ret(); 1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadConstant(Handle<JSObject> object, 11593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 11633bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 11643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> value, 11653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 11683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(receiver, miss); 1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 11713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes( 11723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch object, receiver, holder, scratch1, scratch2, scratch3, name, miss); 1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the constant value. 11753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(r0, value); 1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Ret(); 1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadCallback(Handle<JSObject> object, 11813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 11823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver, 11833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register name_reg, 11843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 11853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch2, 11863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch3, 11873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback, 11883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 11893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 11913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(receiver, miss); 1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 11943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register reg = CheckPrototypes(object, receiver, holder, scratch1, 11953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch2, scratch3, name, miss); 1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1197e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Build AccessorInfo::args_ list on the stack and push property name below 1198e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // the exit frame to make GC aware of them and store pointers to them. 1199e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(receiver); 1200e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(scratch2, sp); // scratch2 = AccessorInfo::args_ 12013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (heap()->InNewSpace(callback->data())) { 12023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(scratch3, callback); 1203e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(scratch3, FieldMemOperand(scratch3, AccessorInfo::kDataOffset)); 1204e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 12053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(scratch3, Handle<Object>(callback->data())); 1206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 1207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Push(reg, scratch3, name_reg); 1208e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(r0, sp); // r0 = Handle<String> 1209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch const int kApiStackSpace = 1; 12113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope frame_scope(masm(), StackFrame::MANUAL); 1212e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ EnterExitFrame(false, kApiStackSpace); 12133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1214e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Create AccessorInfo instance on the stack above the exit frame with 12153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // scratch2 (internal::Object** args_) as the data. 1216e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ str(scratch2, MemOperand(sp, 1 * kPointerSize)); 1217e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ add(r1, sp, Operand(1 * kPointerSize)); // r1 = AccessorInfo& 1218e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1219e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch const int kStackUnwindSpace = 4; 12203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Address getter_address = v8::ToCData<Address>(callback->getter()); 12213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ApiFunction fun(getter_address); 1222e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ExternalReference ref = 122344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(&fun, 122444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::DIRECT_GETTER_CALL, 122544f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm()->isolate()); 12263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallApiFunctionAndReturn(ref, kStackUnwindSpace); 1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object, 12313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> interceptor_holder, 1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupResult* lookup, 1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register name_reg, 1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 12373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 12383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss) { 12407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(interceptor_holder->HasNamedInterceptor()); 12417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); 12427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the receiver isn't a smi. 12441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(receiver, miss); 12457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // So far the most popular follow ups for interceptor loads are FIELD 12477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // and CALLBACKS, so inline only them, other cases may be added 12487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // later. 12497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch bool compile_followup_inline = false; 12503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (lookup->IsFound() && lookup->IsCacheable()) { 12517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (lookup->type() == FIELD) { 12527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch compile_followup_inline = true; 12537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else if (lookup->type() == CALLBACKS && 12543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lookup->GetCallbackObject()->IsAccessorInfo()) { 12553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch compile_followup_inline = 12563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL; 12577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 12587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 12597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (compile_followup_inline) { 12617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Compile the interceptor call, followed by inline code to load the 12627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // property from further up the prototype chain if the call fails. 12637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps haven't changed. 12647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, 12653bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch1, scratch2, scratch3, 12663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch name, miss); 12677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1)); 12687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12695710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch // Preserve the receiver register explicitly whenever it is different from 12705710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch // the holder and it is needed should the interceptor return without any 12715710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch // result. The CALLBACKS case needs the receiver to be passed into C++ code, 12725710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch // the FIELD case might cause a miss during the prototype check. 12735710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder(); 12745710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch bool must_preserve_receiver_reg = !receiver.is(holder_reg) && 12755710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch (lookup->type() == CALLBACKS || must_perfrom_prototype_check); 12765710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch 12777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Save necessary data before invoking an interceptor. 12787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Requires a frame to make GC aware of pushed pointers. 12793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 12803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope frame_scope(masm(), StackFrame::INTERNAL); 12815710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch if (must_preserve_receiver_reg) { 12823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(receiver, holder_reg, name_reg); 12833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(holder_reg, name_reg); 12853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 12863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Invoke an interceptor. Note: map checks from receiver to 12873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // interceptor's holder has been compiled before (see a caller 12883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // of this method.) 12893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompileCallLoadPropertyWithInterceptor(masm(), 12903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver, 12913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch holder_reg, 12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name_reg, 12933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch interceptor_holder); 12943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if interceptor provided a value for property. If it's 12953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the case, return immediately. 12963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label interceptor_failed; 12973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex); 12983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r0, scratch1); 12993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(eq, &interceptor_failed); 13003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch frame_scope.GenerateLeaveFrame(); 13013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(); 130285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 13033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&interceptor_failed); 13043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(name_reg); 13053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(holder_reg); 13065710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch if (must_preserve_receiver_reg) { 13073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(receiver); 13083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 13093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Leave the internal frame. 131085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch } 13117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps from interceptor's holder to lookup's holder 13127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // haven't changed. And load lookup's holder into |holder| register. 13135710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch if (must_perfrom_prototype_check) { 13147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch holder_reg = CheckPrototypes(interceptor_holder, 13157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch holder_reg, 13163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(lookup->holder()), 13177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch1, 13187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch2, 13193bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch3, 13207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch name, 13217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch miss); 13227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 13237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (lookup->type() == FIELD) { 13257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // We found FIELD property in prototype chain of interceptor's holder. 13267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Retrieve a field from field's holder. 13277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateFastPropertyLoad(masm(), r0, holder_reg, 13283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(lookup->holder()), 13293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lookup->GetFieldIndex()); 13307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Ret(); 13317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 13327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // We found CALLBACKS property in prototype chain of interceptor's 13337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // holder. 13347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(lookup->type() == CALLBACKS); 13353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback( 13363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AccessorInfo::cast(lookup->GetCallbackObject())); 13377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(callback->getter() != NULL); 13387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Tail call to runtime. 13407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Important invariant in CALLBACKS case: the code above must be 13417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // structured to never clobber |receiver| register. 13423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(scratch2, callback); 13437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // holder_reg is either receiver or scratch1. 13447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (!receiver.is(holder_reg)) { 13457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(scratch1.is(holder_reg)); 13468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Push(receiver, holder_reg); 13478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(scratch3, 13488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang FieldMemOperand(scratch2, AccessorInfo::kDataOffset)); 13498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Push(scratch3, scratch2, name_reg); 13507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 13517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(receiver); 13528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(scratch3, 13538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang FieldMemOperand(scratch2, AccessorInfo::kDataOffset)); 13548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Push(holder_reg, scratch3, scratch2, name_reg); 13557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 13567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ExternalReference ref = 135844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kLoadCallbackProperty), 135944f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm()->isolate()); 13607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ TailCallExternalReference(ref, 5, 1); 13617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 13627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { // !compile_followup_inline 13637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Call the runtime system to load the interceptor. 13647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps haven't changed. 13657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, 13663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch1, scratch2, scratch3, 13673bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch name, miss); 13687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch PushInterceptorArguments(masm(), receiver, holder_reg, 13697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch name_reg, interceptor_holder); 13707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 137144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference ref = 137244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), 137344f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm()->isolate()); 13747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ TailCallExternalReference(ref, 5, 1); 13757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { 13809dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (kind_ == Code::KEYED_CALL_IC) { 13813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r2, Operand(name)); 13829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ b(ne, miss); 13839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 13849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 13859dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 13869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 13873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object, 13883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 13893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 139059151504615d929945dc59db37bf1166937748c6Steve Block Label* miss) { 139159151504615d929945dc59db37bf1166937748c6Steve Block ASSERT(holder->IsGlobalObject()); 139259151504615d929945dc59db37bf1166937748c6Steve Block 139359151504615d929945dc59db37bf1166937748c6Steve Block // Get the number of arguments. 139459151504615d929945dc59db37bf1166937748c6Steve Block const int argc = arguments().immediate(); 139559151504615d929945dc59db37bf1166937748c6Steve Block 139659151504615d929945dc59db37bf1166937748c6Steve Block // Get the receiver from the stack. 139759151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(r0, MemOperand(sp, argc * kPointerSize)); 139859151504615d929945dc59db37bf1166937748c6Steve Block 139959151504615d929945dc59db37bf1166937748c6Steve Block // Check that the maps haven't changed. 14003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(r0, miss); 140159151504615d929945dc59db37bf1166937748c6Steve Block CheckPrototypes(object, r0, holder, r3, r1, r4, name, miss); 140259151504615d929945dc59db37bf1166937748c6Steve Block} 140359151504615d929945dc59db37bf1166937748c6Steve Block 140459151504615d929945dc59db37bf1166937748c6Steve Block 14053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateLoadFunctionFromCell( 14063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 14073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 14083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 140959151504615d929945dc59db37bf1166937748c6Steve Block // Get the value from the cell. 14103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r3, Operand(cell)); 141159151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); 141259151504615d929945dc59db37bf1166937748c6Steve Block 141359151504615d929945dc59db37bf1166937748c6Steve Block // Check that the cell contains the same function. 14143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (heap()->InNewSpace(*function)) { 141559151504615d929945dc59db37bf1166937748c6Steve Block // We can't embed a pointer to a function in new space so we have 141659151504615d929945dc59db37bf1166937748c6Steve Block // to verify that the shared function info is unchanged. This has 141759151504615d929945dc59db37bf1166937748c6Steve Block // the nice side effect that multiple closures based on the same 141859151504615d929945dc59db37bf1166937748c6Steve Block // function can all use this call IC. Before we load through the 141959151504615d929945dc59db37bf1166937748c6Steve Block // function, we have to verify that it still is a function. 14203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(r1, miss); 142159151504615d929945dc59db37bf1166937748c6Steve Block __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); 142259151504615d929945dc59db37bf1166937748c6Steve Block __ b(ne, miss); 142359151504615d929945dc59db37bf1166937748c6Steve Block 142459151504615d929945dc59db37bf1166937748c6Steve Block // Check the shared function info. Make sure it hasn't changed. 142559151504615d929945dc59db37bf1166937748c6Steve Block __ Move(r3, Handle<SharedFunctionInfo>(function->shared())); 142659151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 142759151504615d929945dc59db37bf1166937748c6Steve Block __ cmp(r4, r3); 142859151504615d929945dc59db37bf1166937748c6Steve Block } else { 14293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r1, Operand(function)); 143059151504615d929945dc59db37bf1166937748c6Steve Block } 14313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, miss); 143259151504615d929945dc59db37bf1166937748c6Steve Block} 143359151504615d929945dc59db37bf1166937748c6Steve Block 143459151504615d929945dc59db37bf1166937748c6Steve Block 14353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateMissBranch() { 14363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = 1437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), 1438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch kind_, 14393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch extra_state_); 14403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(code, RelocInfo::CODE_TARGET); 14417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 14427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14443ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, 14453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 14465913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index, 14473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1449402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- r2 : name 1450402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- lr : return address 1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateNameCheck(name, &miss); 14559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 1456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver of the function from the stack into r0. 1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(sp, argc * kPointerSize)); 1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 14613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(r0, &miss); 1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do the right check and compute the holder register. 14643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register reg = CheckPrototypes(object, r0, holder, r1, r3, r4, name, &miss); 1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateFastPropertyLoad(masm(), r1, reg, holder, index); 1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); 1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 14713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(FIELD, name); 1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14783ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPushCall( 14793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 14803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 14813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 14823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 14833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 14846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 14856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- r2 : name 14866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- lr : return address 14878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 14888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- ... 14898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- sp[argc * 4] : receiver 14906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 14916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 149259151504615d929945dc59db37bf1166937748c6Steve Block // If object is not an array, bail out to regular call. 14933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); 14946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss; 14969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateNameCheck(name, &miss); 14979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 14988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register receiver = r1; 14996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the receiver from the stack 15006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int argc = arguments().immediate(); 15018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); 15026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the receiver isn't a smi. 15041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(receiver, &miss); 15056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the maps haven't changed. 15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, r3, r0, r4, 15083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 15096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang if (argc == 0) { 15118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Nothing to do, just return the length. 15128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 15138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(argc + 1); 15148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 15158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } else { 15168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label call_builtin; 15178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 15183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (argc == 1) { // Otherwise fall through to call the builtin. 15193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label attempt_to_grow_elements; 15208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 15213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register elements = r6; 15223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register end_elements = r5; 15233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the elements array of the object. 15243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); 15255d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 15263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that the elements are in fast mode and writable. 15273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(elements, 15283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r0, 15293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kFixedArrayMapRootIndex, 15303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &call_builtin, 15313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DONT_DO_SMI_CHECK); 15325d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 15335d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 15348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Get the array's length into r0 and calculate new length. 15358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 15368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang STATIC_ASSERT(kSmiTagSize == 1); 15378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang STATIC_ASSERT(kSmiTag == 0); 15388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ add(r0, r0, Operand(Smi::FromInt(argc))); 15398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 15403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the elements' length. 15418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset)); 15428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 15438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check if we could survive without allocation. 15448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ cmp(r0, r4); 15458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(gt, &attempt_to_grow_elements); 15468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 15473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if value is a smi. 15483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label with_write_barrier; 15493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r4, MemOperand(sp, (argc - 1) * kPointerSize)); 15503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfNotSmi(r4, &with_write_barrier); 15513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Save new length. 15538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 15548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 15553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the value. 15568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // We may need a register containing the address end_elements below, 15578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // so write back the value in end_elements. 15588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ add(end_elements, elements, 15598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); 15608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const int kEndElementsOffset = 15618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize; 15628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex)); 15638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 15648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check for a smi. 15658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(argc + 1); 15668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 15678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 15688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&with_write_barrier); 15693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r3, FieldMemOperand(receiver, HeapObject::kMapOffset)); 15713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) { 15733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label fast_object, not_fast_object; 15743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastObjectElements(r3, r7, ¬_fast_object); 15753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&fast_object); 15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // In case of fast smi-only, convert to fast object, otherwise bail out. 15773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(¬_fast_object); 15783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastSmiOnlyElements(r3, r7, &call_builtin); 15793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // edx: receiver 15803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r3: map 15813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS, 15823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FAST_ELEMENTS, 15833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r3, 15843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r7, 15853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &call_builtin); 15863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r2, receiver); 15873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsTransitionGenerator::GenerateSmiOnlyToObject(masm()); 15883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&fast_object); 15893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 15903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastObjectElements(r3, r3, &call_builtin); 15913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 15923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Save new length. 15943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 15953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the value. 15973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We may need a register containing the address end_elements below, 15983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // so write back the value in end_elements. 15993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(end_elements, elements, 16003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); 16013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex)); 16023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 16033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWrite(elements, 16043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch end_elements, 16053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r4, 16063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kLRHasNotBeenSaved, 16073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, 16083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, 16093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_SMI_CHECK); 16108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(argc + 1); 16118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 16128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 16138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&attempt_to_grow_elements); 16148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // r0: array's length + 1. 16158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // r4: elements' length. 16168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 16178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang if (!FLAG_inline_new) { 16188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&call_builtin); 16198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 16208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 16213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r2, MemOperand(sp, (argc - 1) * kPointerSize)); 16223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Growing elements that are SMI-only requires special handling in case 16233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the new element is non-Smi. For now, delegate to the builtin. 16243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label no_fast_elements_check; 16253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(r2, &no_fast_elements_check); 16263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r7, FieldMemOperand(receiver, HeapObject::kMapOffset)); 16273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastObjectElements(r7, r7, &call_builtin); 16283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&no_fast_elements_check); 16293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 163044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate = masm()->isolate(); 16318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ExternalReference new_space_allocation_top = 163244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::new_space_allocation_top_address(isolate); 16338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ExternalReference new_space_allocation_limit = 163444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::new_space_allocation_limit_address(isolate); 16358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 16368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const int kAllocationDelta = 4; 16378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load top and check if it is the end of elements. 16388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ add(end_elements, elements, 16398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); 16408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ add(end_elements, end_elements, Operand(kEndElementsOffset)); 16418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(r7, Operand(new_space_allocation_top)); 16423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r3, MemOperand(r7)); 16433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(end_elements, r3); 16448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(ne, &call_builtin); 16458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 16468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(r9, Operand(new_space_allocation_limit)); 16478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r9, MemOperand(r9)); 16483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(r3, r3, Operand(kAllocationDelta * kPointerSize)); 16493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r3, r9); 16508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(hi, &call_builtin); 16518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 16528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // We fit and could grow elements. 16538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Update new_space_allocation_top. 16543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r3, MemOperand(r7)); 16558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Push the argument. 16563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r2, MemOperand(end_elements)); 16578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Fill the rest with holes. 16583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r3, Heap::kTheHoleValueRootIndex); 16598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang for (int i = 1; i < kAllocationDelta; i++) { 16603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r3, MemOperand(end_elements, i * kPointerSize)); 16618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 16628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 16638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Update elements' and array's sizes. 16648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 16658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ add(r4, r4, Operand(Smi::FromInt(kAllocationDelta))); 16668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(r4, FieldMemOperand(elements, FixedArray::kLengthOffset)); 16678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 16688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Elements are in new space, so write barrier is not required. 16698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(argc + 1); 16708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 16718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 16728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&call_builtin); 167344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush, 167444f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm()->isolate()), 16758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang argc + 1, 16768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1); 16778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 16786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Handle call cache miss. 16806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss); 16813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 16826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return the generated code. 168425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen return GetCode(function); 16856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 16866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16883ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPopCall( 16893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 16903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 16913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 16923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 16933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 1694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1695402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- r2 : name 1696402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- lr : return address 16978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 16988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- ... 16998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- sp[argc * 4] : receiver 1700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 17016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 170259151504615d929945dc59db37bf1166937748c6Steve Block // If object is not an array, bail out to regular call. 17033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); 17046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label miss, return_undefined, call_builtin; 17068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register receiver = r1; 17078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register elements = r3; 17089dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateNameCheck(name, &miss); 17099dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 1710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver from the stack 1711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 17128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); 1713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 17141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(receiver, &miss); 17156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the maps haven't changed. 17173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, elements, 17183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r4, r0, name, &miss); 17198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 17208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Get the elements array of the object. 17218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); 17226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check that the elements are in fast mode and writable. 1724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CheckMap(elements, 1725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch r0, 1726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Heap::kFixedArrayMapRootIndex, 1727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &call_builtin, 1728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DONT_DO_SMI_CHECK); 17298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 17308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Get the array's length into r4 and calculate new length. 17318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r4, FieldMemOperand(receiver, JSArray::kLengthOffset)); 17328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ sub(r4, r4, Operand(Smi::FromInt(1)), SetCC); 17338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(lt, &return_undefined); 17348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 17358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Get the last element. 17368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ LoadRoot(r6, Heap::kTheHoleValueRootIndex); 17378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang STATIC_ASSERT(kSmiTagSize == 1); 17388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang STATIC_ASSERT(kSmiTag == 0); 17398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // We can't address the last element in one operation. Compute the more 17408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // expensive shift first, and use an offset later on. 17418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ add(elements, elements, Operand(r4, LSL, kPointerSizeLog2 - kSmiTagSize)); 17428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r0, MemOperand(elements, FixedArray::kHeaderSize - kHeapObjectTag)); 17438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ cmp(r0, r6); 17448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(eq, &call_builtin); 17458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 17468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Set the array's length. 17478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(r4, FieldMemOperand(receiver, JSArray::kLengthOffset)); 17488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 17498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Fill with the hole. 17508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(r6, MemOperand(elements, FixedArray::kHeaderSize - kHeapObjectTag)); 17518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(argc + 1); 17528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 17538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 17548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&return_undefined); 17558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 17568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(argc + 1); 17578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 17588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 17598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&call_builtin); 176044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop, 176144f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm()->isolate()), 17626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block argc + 1, 17636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1); 17646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Handle call cache miss. 17666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss); 17673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 17686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return the generated code. 177025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen return GetCode(function); 17716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 17726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17743ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharCodeAtCall( 17753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 17763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 17773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 17783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 17793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 178080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ----------- S t a t e ------------- 178180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- r2 : function name 178280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- lr : return address 178380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 178480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- ... 178580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- sp[argc * 4] : receiver 178680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ----------------------------------- 178780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 178880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // If object is not a string, bail out to regular call. 17893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); 179080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 179180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen const int argc = arguments().immediate(); 179280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label miss; 1793b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label name_miss; 179480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label index_out_of_range; 1795b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label* index_out_of_range_label = &index_out_of_range; 1796b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (kind_ == Code::CALL_IC && 17983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (CallICBase::StringStubState::decode(extra_state_) == 1799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DEFAULT_STRING_STUB)) { 1800b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch index_out_of_range_label = &miss; 1801b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1802b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch GenerateNameCheck(name, &name_miss); 180380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 180480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check that the maps starting from the prototype haven't changed. 180580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen GenerateDirectLoadGlobalFunctionPrototype(masm(), 180680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Context::STRING_FUNCTION_INDEX, 18070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen r0, 18080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &miss); 18093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!object.is_identical_to(holder)); 18103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())), 18113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r0, holder, r1, r3, r4, name, &miss); 181280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 181380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Register receiver = r1; 181480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Register index = r4; 181580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Register result = r0; 181680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); 181780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (argc > 0) { 181880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize)); 181980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 182080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadRoot(index, Heap::kUndefinedValueRootIndex); 182180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 182280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 18233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringCharCodeAtGenerator generator(receiver, 18243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index, 18253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result, 18263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a string. 18273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a number. 18283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index_out_of_range_label, 18293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STRING_INDEX_IS_NUMBER); 18303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateFast(masm()); 183180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Drop(argc + 1); 183280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Ret(); 183380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch StubRuntimeCallHelper call_helper; 18353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateSlow(masm(), call_helper); 183680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1837b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (index_out_of_range.is_linked()) { 1838b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&index_out_of_range); 1839b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ LoadRoot(r0, Heap::kNanValueRootIndex); 1840b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ Drop(argc + 1); 1841b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ Ret(); 1842b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 184380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 184480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&miss); 1845b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Restore function name in r2. 18463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(r2, name); 1847b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&name_miss); 18483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 184980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 185080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Return the generated code. 185180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen return GetCode(function); 18527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 18537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 18547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 18553ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharAtCall( 18563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 18573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 18583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 18593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 18603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 186180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ----------- S t a t e ------------- 186280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- r2 : function name 186380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- lr : return address 186480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 186580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- ... 186680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- sp[argc * 4] : receiver 186780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ----------------------------------- 186880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 186980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // If object is not a string, bail out to regular call. 18703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); 187180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 187280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen const int argc = arguments().immediate(); 187380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label miss; 1874b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label name_miss; 187580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label index_out_of_range; 1876b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label* index_out_of_range_label = &index_out_of_range; 1877257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (kind_ == Code::CALL_IC && 18783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (CallICBase::StringStubState::decode(extra_state_) == 1879257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DEFAULT_STRING_STUB)) { 1880b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch index_out_of_range_label = &miss; 1881b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1882b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch GenerateNameCheck(name, &name_miss); 188380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 188480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check that the maps starting from the prototype haven't changed. 188580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen GenerateDirectLoadGlobalFunctionPrototype(masm(), 188680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Context::STRING_FUNCTION_INDEX, 18870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen r0, 18880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &miss); 18893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!object.is_identical_to(holder)); 18903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())), 18913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r0, holder, r1, r3, r4, name, &miss); 189280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 189380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Register receiver = r0; 189480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Register index = r4; 18953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch = r3; 189680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Register result = r0; 189780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); 189880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (argc > 0) { 189980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize)); 190080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 190180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadRoot(index, Heap::kUndefinedValueRootIndex); 190280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 190380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 19043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringCharAtGenerator generator(receiver, 19053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index, 19063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 19073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result, 19083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a string. 19093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a number. 19103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index_out_of_range_label, 19113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STRING_INDEX_IS_NUMBER); 19123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateFast(masm()); 191380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Drop(argc + 1); 191480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Ret(); 191580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch StubRuntimeCallHelper call_helper; 19173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateSlow(masm(), call_helper); 191880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1919b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (index_out_of_range.is_linked()) { 1920b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&index_out_of_range); 1921b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ LoadRoot(r0, Heap::kEmptyStringRootIndex); 1922b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ Drop(argc + 1); 1923b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ Ret(); 1924b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 192580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 192680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&miss); 1927b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Restore function name in r2. 19283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(r2, name); 1929b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&name_miss); 19303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 193180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 193280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Return the generated code. 193380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen return GetCode(function); 19347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 19357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 19367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 19373ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringFromCharCodeCall( 19383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 19393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 19403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 19413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 19423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 194359151504615d929945dc59db37bf1166937748c6Steve Block // ----------- S t a t e ------------- 194459151504615d929945dc59db37bf1166937748c6Steve Block // -- r2 : function name 194559151504615d929945dc59db37bf1166937748c6Steve Block // -- lr : return address 194659151504615d929945dc59db37bf1166937748c6Steve Block // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 194759151504615d929945dc59db37bf1166937748c6Steve Block // -- ... 194859151504615d929945dc59db37bf1166937748c6Steve Block // -- sp[argc * 4] : receiver 194959151504615d929945dc59db37bf1166937748c6Steve Block // ----------------------------------- 195059151504615d929945dc59db37bf1166937748c6Steve Block 195159151504615d929945dc59db37bf1166937748c6Steve Block const int argc = arguments().immediate(); 195259151504615d929945dc59db37bf1166937748c6Steve Block 195359151504615d929945dc59db37bf1166937748c6Steve Block // If the object is not a JSObject or we got an unexpected number of 195459151504615d929945dc59db37bf1166937748c6Steve Block // arguments, bail out to the regular call. 19553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); 195659151504615d929945dc59db37bf1166937748c6Steve Block 195759151504615d929945dc59db37bf1166937748c6Steve Block Label miss; 195859151504615d929945dc59db37bf1166937748c6Steve Block GenerateNameCheck(name, &miss); 195959151504615d929945dc59db37bf1166937748c6Steve Block 19603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (cell.is_null()) { 196159151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); 196259151504615d929945dc59db37bf1166937748c6Steve Block 196359151504615d929945dc59db37bf1166937748c6Steve Block STATIC_ASSERT(kSmiTag == 0); 19643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(r1, &miss); 196559151504615d929945dc59db37bf1166937748c6Steve Block 19663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4, 19673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 196859151504615d929945dc59db37bf1166937748c6Steve Block } else { 19693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(cell->value() == *function); 19703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 19713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 197259151504615d929945dc59db37bf1166937748c6Steve Block GenerateLoadFunctionFromCell(cell, function, &miss); 197359151504615d929945dc59db37bf1166937748c6Steve Block } 197459151504615d929945dc59db37bf1166937748c6Steve Block 197559151504615d929945dc59db37bf1166937748c6Steve Block // Load the char code argument. 197659151504615d929945dc59db37bf1166937748c6Steve Block Register code = r1; 197759151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(code, MemOperand(sp, 0 * kPointerSize)); 197859151504615d929945dc59db37bf1166937748c6Steve Block 197959151504615d929945dc59db37bf1166937748c6Steve Block // Check the code is a smi. 198059151504615d929945dc59db37bf1166937748c6Steve Block Label slow; 198159151504615d929945dc59db37bf1166937748c6Steve Block STATIC_ASSERT(kSmiTag == 0); 19823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(code, &slow); 198359151504615d929945dc59db37bf1166937748c6Steve Block 198459151504615d929945dc59db37bf1166937748c6Steve Block // Convert the smi code to uint16. 198559151504615d929945dc59db37bf1166937748c6Steve Block __ and_(code, code, Operand(Smi::FromInt(0xffff))); 198659151504615d929945dc59db37bf1166937748c6Steve Block 19873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringCharFromCodeGenerator generator(code, r0); 19883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateFast(masm()); 198959151504615d929945dc59db37bf1166937748c6Steve Block __ Drop(argc + 1); 199059151504615d929945dc59db37bf1166937748c6Steve Block __ Ret(); 199159151504615d929945dc59db37bf1166937748c6Steve Block 1992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch StubRuntimeCallHelper call_helper; 19933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateSlow(masm(), call_helper); 199459151504615d929945dc59db37bf1166937748c6Steve Block 199559151504615d929945dc59db37bf1166937748c6Steve Block // Tail call the full function. We do not have to patch the receiver 199659151504615d929945dc59db37bf1166937748c6Steve Block // because the function makes no use of it. 199759151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&slow); 19983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeFunction( 19993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); 200059151504615d929945dc59db37bf1166937748c6Steve Block 200159151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&miss); 200259151504615d929945dc59db37bf1166937748c6Steve Block // r2: function name. 20033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 200459151504615d929945dc59db37bf1166937748c6Steve Block 200559151504615d929945dc59db37bf1166937748c6Steve Block // Return the generated code. 20063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); 200759151504615d929945dc59db37bf1166937748c6Steve Block} 200859151504615d929945dc59db37bf1166937748c6Steve Block 200959151504615d929945dc59db37bf1166937748c6Steve Block 20103ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathFloorCall( 20113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 20123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 20133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 20143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 20153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 20168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // ----------- S t a t e ------------- 20178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- r2 : function name 20188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- lr : return address 20198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 20208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- ... 20218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- sp[argc * 4] : receiver 20228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // ----------------------------------- 20238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (!CpuFeatures::IsSupported(VFP3)) { 20253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Handle<Code>::null(); 202644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 202744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 20288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CpuFeatures::Scope scope_vfp3(VFP3); 20298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const int argc = arguments().immediate(); 20308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // If the object is not a JSObject or we got an unexpected number of 20318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // arguments, bail out to the regular call. 20323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); 20338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label miss, slow; 20358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GenerateNameCheck(name, &miss); 20368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (cell.is_null()) { 20388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); 20398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang STATIC_ASSERT(kSmiTag == 0); 20401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r1, &miss); 20413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4, 20423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 20438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } else { 20443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(cell->value() == *function); 20453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 20463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 20478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GenerateLoadFunctionFromCell(cell, function, &miss); 20488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 20498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load the (only) argument into r0. 20518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); 20528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // If the argument is a smi, just return. 20548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang STATIC_ASSERT(kSmiTag == 0); 20558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ tst(r0, Operand(kSmiTagMask)); 20568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(argc + 1, eq); 20578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(eq); 20588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 2059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK); 20608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label wont_fit_smi, no_vfp_exception, restore_fpscr_and_return; 20628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // If vfp3 is enabled, we use the fpu rounding with the RM (round towards 20648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // minus infinity) mode. 20658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load the HeapNumber value. 20678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // We will need access to the value in the core registers, so we load it 20688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // with ldrd and move it to the fpu. It also spares a sub instruction for 20698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // updating the HeapNumber value address, as vldr expects a multiple 20708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // of 4 offset. 20718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ldrd(r4, r5, FieldMemOperand(r0, HeapNumber::kValueOffset)); 20728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ vmov(d1, r4, r5); 20738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Backup FPSCR. 20758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ vmrs(r3); 20768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Set custom FPCSR: 20778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // - Set rounding mode to "Round towards Minus Infinity" 20783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // (i.e. bits [23:22] = 0b10). 20798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // - Clear vfp cumulative exception flags (bits [3:0]). 20808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // - Make sure Flush-to-zero mode control bit is unset (bit 22). 20818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bic(r9, r3, 20828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Operand(kVFPExceptionMask | kVFPRoundingModeMask | kVFPFlushToZeroMask)); 20831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ orr(r9, r9, Operand(kRoundToMinusInf)); 20848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ vmsr(r9); 20858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Convert the argument to an integer. 20871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ vcvt_s32_f64(s0, d1, kFPSCRRounding); 20888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Use vcvt latency to start checking for special cases. 20908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Get the argument exponent and clear the sign bit. 20918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bic(r6, r5, Operand(HeapNumber::kSignMask)); 20928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(r6, Operand(r6, LSR, HeapNumber::kMantissaBitsInTopWord)); 20938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Retrieve FPSCR and check for vfp exceptions. 20958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ vmrs(r9); 20968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ tst(r9, Operand(kVFPExceptionMask)); 20978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&no_vfp_exception, eq); 20988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check for NaN, Infinity, and -Infinity. 21008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // They are invariant through a Math.Floor call, so just 21018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // return the original argument. 21028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ sub(r7, r6, Operand(HeapNumber::kExponentMask 21038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang >> HeapNumber::kMantissaBitsInTopWord), SetCC); 21048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&restore_fpscr_and_return, eq); 21058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // We had an overflow or underflow in the conversion. Check if we 21068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // have a big exponent. 21078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ cmp(r7, Operand(HeapNumber::kMantissaBits)); 21088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // If greater or equal, the argument is already round and in r0. 21098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&restore_fpscr_and_return, ge); 2110b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ b(&wont_fit_smi); 21118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 21128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&no_vfp_exception); 21138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Move the result back to general purpose register r0. 21148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ vmov(r0, s0); 21158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check if the result fits into a smi. 21168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ add(r1, r0, Operand(0x40000000), SetCC); 21178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&wont_fit_smi, mi); 21188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Tag the result. 21198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang STATIC_ASSERT(kSmiTag == 0); 21208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(r0, Operand(r0, LSL, kSmiTagSize)); 21218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 21228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check for -0. 2123b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ cmp(r0, Operand(0, RelocInfo::NONE)); 21248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&restore_fpscr_and_return, ne); 21258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // r5 already holds the HeapNumber exponent. 21268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ tst(r5, Operand(HeapNumber::kSignMask)); 21278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // If our HeapNumber is negative it was -0, so load its address and return. 21288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Else r0 is loaded with 0, so we can also just return. 21298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r0, MemOperand(sp, 0 * kPointerSize), ne); 21308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 21318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&restore_fpscr_and_return); 21328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Restore FPSCR and return. 21338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ vmsr(r3); 21348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(argc + 1); 21358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 21368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 21378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&wont_fit_smi); 21388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Restore FPCSR and fall to slow case. 21398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ vmsr(r3); 21408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 2141b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&slow); 21428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Tail call the full function. We do not have to patch the receiver 21438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // because the function makes no use of it. 21443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeFunction( 21453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); 21468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 21478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&miss); 21488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // r2: function name. 21493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 21508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 21518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Return the generated code. 21523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); 21530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 21540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 21550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 21563ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathAbsCall( 21573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 21583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 21593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 21603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 21613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2162f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // ----------- S t a t e ------------- 2163f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- r2 : function name 2164f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- lr : return address 2165f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 2166f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- ... 2167f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- sp[argc * 4] : receiver 2168f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // ----------------------------------- 2169f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2170f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch const int argc = arguments().immediate(); 2171f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // If the object is not a JSObject or we got an unexpected number of 2172f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // arguments, bail out to the regular call. 21733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); 2174f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2175f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Label miss; 2176f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch GenerateNameCheck(name, &miss); 21773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (cell.is_null()) { 2178f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); 2179f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch STATIC_ASSERT(kSmiTag == 0); 21803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(r1, &miss); 21813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4, 21823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 2183f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch } else { 21843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(cell->value() == *function); 21853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 21863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 2187f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch GenerateLoadFunctionFromCell(cell, function, &miss); 2188f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch } 2189f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2190f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Load the (only) argument into r0. 2191f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); 2192f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2193f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Check if the argument is a smi. 2194f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Label not_smi; 2195f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch STATIC_ASSERT(kSmiTag == 0); 21961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfNotSmi(r0, ¬_smi); 2197f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2198f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Do bitwise not or do nothing depending on the sign of the 2199f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // argument. 2200f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ eor(r1, r0, Operand(r0, ASR, kBitsPerInt - 1)); 2201f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2202f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Add 1 or do nothing depending on the sign of the argument. 2203f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ sub(r0, r1, Operand(r0, ASR, kBitsPerInt - 1), SetCC); 2204f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2205f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // If the result is still negative, go to the slow case. 2206f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // This only happens for the most negative smi. 2207f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Label slow; 2208f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ b(mi, &slow); 2209f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2210f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Smi case done. 2211f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ Drop(argc + 1); 2212f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ Ret(); 2213f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2214f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Check if the argument is a heap number and load its exponent and 2215f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // sign. 2216f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(¬_smi); 2217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK); 2218f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ ldr(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset)); 2219f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2220f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Check the sign of the argument. If the argument is positive, 2221f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // just return it. 2222f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Label negative_sign; 2223f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ tst(r1, Operand(HeapNumber::kSignMask)); 2224f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ b(ne, &negative_sign); 2225f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ Drop(argc + 1); 2226f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ Ret(); 2227f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2228f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // If the argument is negative, clear the sign, and return a new 2229f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // number. 2230f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(&negative_sign); 2231f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ eor(r1, r1, Operand(HeapNumber::kSignMask)); 2232f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); 2233f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); 2234f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ AllocateHeapNumber(r0, r4, r5, r6, &slow); 2235f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ str(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset)); 2236f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ str(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); 2237f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ Drop(argc + 1); 2238f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ Ret(); 2239f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2240f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Tail call the full function. We do not have to patch the receiver 2241f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // because the function makes no use of it. 2242f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(&slow); 22433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeFunction( 22443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); 2245f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2246f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(&miss); 2247f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // r2: function name. 22483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2249f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2250f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Return the generated code. 22513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); 2252f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch} 2253f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2254f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 22553ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileFastApiCall( 225644f0eee88ff00398ff7f715fab053374d808c90dSteve Block const CallOptimization& optimization, 22573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 22583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 22593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 22603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 22613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 226244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 226344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 226444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(optimization.is_simple_api_call()); 226544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Bail out if object is a global object as we don't want to 226644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // repatch it to global receiver. 22673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (object->IsGlobalObject()) return Handle<Code>::null(); 22683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!cell.is_null()) return Handle<Code>::null(); 22693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSObject()) return Handle<Code>::null(); 227044f0eee88ff00398ff7f715fab053374d808c90dSteve Block int depth = optimization.GetPrototypeDepthOfExpectedType( 22713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>::cast(object), holder); 22723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (depth == kInvalidProtoDepth) return Handle<Code>::null(); 227344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 227444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label miss, miss_before_stack_reserved; 227544f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenerateNameCheck(name, &miss_before_stack_reserved); 227644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 227744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Get the receiver from the stack. 227844f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int argc = arguments().immediate(); 227944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ ldr(r1, MemOperand(sp, argc * kPointerSize)); 228044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 228144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the receiver isn't a smi. 22823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(r1, &miss_before_stack_reserved); 228344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 228444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_const(), 1, r0, r3); 228544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_const_fast_api(), 1, r0, r3); 228644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 228744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ReserveSpaceForFastApiCall(masm(), r0); 228844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 228944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the maps haven't changed and find a Holder as a side effect. 22903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4, name, 229144f0eee88ff00398ff7f715fab053374d808c90dSteve Block depth, &miss); 229244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 22933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateFastApiDirectCall(masm(), optimization, argc); 229444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 229544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&miss); 229644f0eee88ff00398ff7f715fab053374d808c90dSteve Block FreeSpaceForFastApiCall(masm()); 229744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 229844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&miss_before_stack_reserved); 22993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 230044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 230144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Return the generated code. 230244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return GetCode(function); 230344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 230444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 230544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 23063ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object, 23073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 23083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 23093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 23105913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck CheckType check) { 23116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 23126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- r2 : name 23136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- lr : return address 23146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 231544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (HasCustomCallGenerator(function)) { 23163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = CompileCustomCall(object, holder, 23173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell>::null(), 23183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function, name); 23193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // A null handle means bail out to the regular compiler code below. 23203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!code.is_null()) return code; 23216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 23226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 232344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label miss; 232444f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenerateNameCheck(name, &miss); 23259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 23266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the receiver from the stack 23276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int argc = arguments().immediate(); 23286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ldr(r1, MemOperand(sp, argc * kPointerSize)); 23296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 23306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the receiver isn't a smi. 2331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check != NUMBER_CHECK) { 23323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(r1, &miss); 2333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure that it's okay not to patch the on stack receiver 2336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // unless we're doing a receiver map check. 2337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); 2338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (check) { 2339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case RECEIVER_MAP_CHECK: 234044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(masm()->isolate()->counters()->call_const(), 234144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1, r0, r3); 23426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 23443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4, 23453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 2346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack with the global proxy if 2348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // necessary. 2349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsGlobalObject()) { 2350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); 2351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r3, MemOperand(sp, argc * kPointerSize)); 2352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 2354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case STRING_CHECK: 23563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (function->IsBuiltin() || !function->shared()->is_classic_mode()) { 2357e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the object is a two-byte string or a symbol. 2358402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE); 23593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ b(ge, &miss); 2360e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the maps starting from the prototype haven't changed. 23617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype( 23620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen masm(), Context::STRING_FUNCTION_INDEX, r0, &miss); 23633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes( 23643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(JSObject::cast(object->GetPrototype())), 23653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r0, holder, r3, r1, r4, name, &miss); 23663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 236785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // Calling non-strict non-builtins with a value as the receiver 236885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // requires boxing. 236985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch __ jmp(&miss); 23703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 23713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 23723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 23733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case NUMBER_CHECK: 23743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (function->IsBuiltin() || !function->shared()->is_classic_mode()) { 2375e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label fast; 2376e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the object is a smi or a heap number. 23773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(r1, &fast); 2378402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE); 2379e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ b(ne, &miss); 2380e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&fast); 2381e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the maps starting from the prototype haven't changed. 23827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype( 23830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss); 23843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes( 23853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(JSObject::cast(object->GetPrototype())), 23863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r0, holder, r3, r1, r4, name, &miss); 23873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 238885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // Calling non-strict non-builtins with a value as the receiver 238985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // requires boxing. 239085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch __ jmp(&miss); 23913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 23923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 23933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 23943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case BOOLEAN_CHECK: 23953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (function->IsBuiltin() || !function->shared()->is_classic_mode()) { 2396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label fast; 2397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the object is a boolean. 2398e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadRoot(ip, Heap::kTrueValueRootIndex); 2399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(r1, ip); 2400e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ b(eq, &fast); 2401e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadRoot(ip, Heap::kFalseValueRootIndex); 2402e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(r1, ip); 2403e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ b(ne, &miss); 2404e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&fast); 2405e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the maps starting from the prototype haven't changed. 24067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype( 24070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen masm(), Context::BOOLEAN_FUNCTION_INDEX, r0, &miss); 24083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes( 24093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(JSObject::cast(object->GetPrototype())), 24103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r0, holder, r3, r1, r4, name, &miss); 24113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 24123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Calling non-strict non-builtins with a value as the receiver 24133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // requires boxing. 24143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&miss); 2415e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 2417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 2421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 24223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeFunction( 24233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function, arguments(), JUMP_FUNCTION, NullCallWrapper(), call_kind); 2424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 2426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 24273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 243025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen return GetCode(function); 2431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24343ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, 24353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 24363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2438402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- r2 : name 2439402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- lr : return address 2440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 24416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss; 24429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateNameCheck(name, &miss); 24439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 24444515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Get the number of arguments. 24454515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke const int argc = arguments().immediate(); 24463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 24474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke LookupPostInterceptor(holder, name, &lookup); 24484515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 24496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the receiver from the stack. 24506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ldr(r1, MemOperand(sp, argc * kPointerSize)); 2451402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 24523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallInterceptorCompiler compiler(this, arguments(), r2, extra_state_); 24533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch compiler.Compile(masm(), object, holder, name, &lookup, r1, r3, r4, r0, 24543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 2455402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 2456402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Move returned value, the function to call, to r1. 2457402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(r1, r0); 24584515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Restore receiver. 24596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ldr(r0, MemOperand(sp, argc * kPointerSize)); 24604515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 24613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); 2462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 2464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 24653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24723ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallGlobal( 24733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 24743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject> holder, 24753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 24763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 24773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2479402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- r2 : name 2480402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- lr : return address 2481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 248244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (HasCustomCallGenerator(function)) { 24833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = CompileCustomCall(object, holder, cell, function, name); 24843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // A null handle means bail out to the regular compiler code below. 24853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!code.is_null()) return code; 248659151504615d929945dc59db37bf1166937748c6Steve Block } 248759151504615d929945dc59db37bf1166937748c6Steve Block 2488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 24899dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateNameCheck(name, &miss); 24909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 2491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the number of arguments. 2492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 249359151504615d929945dc59db37bf1166937748c6Steve Block GenerateGlobalReceiverCheck(object, holder, name, &miss); 249459151504615d929945dc59db37bf1166937748c6Steve Block GenerateLoadFunctionFromCell(cell, function, &miss); 2495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack with the global proxy if 2497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // necessary. 2498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsGlobalObject()) { 2499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); 2500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r3, MemOperand(sp, argc * kPointerSize)); 2501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the context (function already in r1). 2504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 2505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the cached code (tail call). 250744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = masm()->isolate()->counters(); 250844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_global_inline(), 1, r3, r4); 2509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount expected(function->shared()->formal_parameter_count()); 25103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 2512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 25133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We call indirectly through the code field in the function to 25143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // allow recompilation to take effect without changing any of the 25153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // call sites. 25163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); 25173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeCode(r3, expected, arguments(), JUMP_FUNCTION, 25183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch NullCallWrapper(), call_kind); 2519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 2521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 252244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_global_inline_miss(), 1, r1, r3); 25233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(NORMAL, name); 2527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25303ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, 25315913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index, 25323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> transition, 25333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : value 2536402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- r1 : receiver 2537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 2538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateStoreField(masm(), object, index, transition, r1, r2, r3, &miss); 2543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 254444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); 2545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 2546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 25483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); 2549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25523ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreCallback( 25533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 25543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback, 25553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : value 2558402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- r1 : receiver 2559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 2560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the object hasn't changed. 25653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(r1, r3, Handle<Map>(object->map()), &miss, 25663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); 2567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform global security token check if needed. 2569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsJSGlobalProxy()) { 2570402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CheckAccessGlobalProxy(r1, r3, &miss); 2571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stub never generated for non-global objects that require access 2574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks. 2575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 2576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2577402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(r1); // receiver 25783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ip, Operand(callback)); // callback info 25796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Push(ip, r2, r0); 2580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to the runtime system. 2582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference store_callback_property = 258344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kStoreCallbackProperty), 258444f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm()->isolate()); 25856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(store_callback_property, 4, 1); 2586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 258944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); 2590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 2591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25973ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreInterceptor( 25983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 25993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : value 2602402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- r1 : receiver 2603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 2604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the object hasn't changed. 26093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(r1, r3, Handle<Map>(receiver->map()), &miss, 26103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); 2611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform global security token check if needed. 2613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (receiver->IsJSGlobalProxy()) { 2614402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CheckAccessGlobalProxy(r1, r3, &miss); 2615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2617402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Stub is never generated for non-global objects that require access 2618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks. 2619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); 2620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 26216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Push(r1, r2, r0); // Receiver, name, value. 2622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2623e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(r0, Operand(Smi::FromInt(strict_mode_))); 2624e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(r0); // strict mode 2625e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to the runtime system. 2627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference store_ic_property = 262844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), 262944f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm()->isolate()); 2630e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ TailCallExternalReference(store_ic_property, 4, 1); 2631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 263444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); 2635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 2636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 26423ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreGlobal( 26433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject> object, 26443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 26453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : value 2648402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- r1 : receiver 2649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 2650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the global has not changed. 2655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); 2656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r3, Operand(Handle<Map>(object->map()))); 2657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 2658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 26591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the value in the cell is not the hole. If it is, this 26601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // cell could have been deleted and reintroducing the global needs 26611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // to update the property details in the property dictionary of the 26621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // global object. We bail out to the runtime system to do that. 26633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r4, Operand(cell)); 26641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ LoadRoot(r5, Heap::kTheHoleValueRootIndex); 26651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldr(r6, FieldMemOperand(r4, JSGlobalPropertyCell::kValueOffset)); 26661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmp(r5, r6); 26671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(eq, &miss); 26681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Store the value in the cell. 26701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ str(r0, FieldMemOperand(r4, JSGlobalPropertyCell::kValueOffset)); 26713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Cells are always rescanned, so no write barrier here. 2672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 267344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = masm()->isolate()->counters(); 267444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_store_global_inline(), 1, r4, r3); 2675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Ret(); 2676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 267944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_store_global_inline_miss(), 1, r4, r3); 268044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); 2681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 2682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(NORMAL, name); 2685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 26883ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name, 26893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 26903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> last) { 26916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 2692f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -- r0 : receiver 26936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- lr : return address 26946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 26956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss; 26966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 26976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that receiver is not a smi. 26983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(r0, &miss); 26996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 27006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check the maps of the full prototype chain. 27013bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CheckPrototypes(object, r0, last, r3, r1, r4, name, &miss); 27026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 27036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // If the last object in the prototype chain is a global object, 27046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // check that the global property cell is empty. 27056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (last->IsGlobalObject()) { 27063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateCheckPropertyCell( 27073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm(), Handle<GlobalObject>::cast(last), name, r1, &miss); 27086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 27096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 27106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return undefined if maps of the full prototype chain are still the 27116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // same and no global property with this name contains a value. 27126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 27136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Ret(); 27146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 27156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss); 27166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 27176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 27186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return the generated code. 27193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NONEXISTENT, factory()->empty_string()); 27206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 27216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 27226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 27233ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object, 27243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 27255913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index, 27263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2728f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -- r0 : receiver 2729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 2730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch GenerateLoadField(object, holder, r0, r3, r1, r4, index, name, &miss); 2735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(FIELD, name); 2740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27433ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadCallback( 27443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 27453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 27463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 27473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback) { 2748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2749f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -- r0 : receiver 2750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 2751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 27543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadCallback(object, holder, r0, r2, r3, r1, r4, callback, name, 27553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 2756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27643ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object, 27653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 27663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> value, 27673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -- r0 : receiver 2770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 2771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27753bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch GenerateLoadConstant(object, holder, r0, r3, r1, r4, value, name, &miss); 2776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CONSTANT_FUNCTION, name); 2781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27843ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> object, 27853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 27863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2788f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -- r0 : receiver 2789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 2790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 27954515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke LookupPostInterceptor(holder, name, &lookup); 27963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadInterceptor(object, holder, &lookup, r0, r2, r3, r1, r4, name, 2797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &miss); 2798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28063ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadGlobal( 28073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 28083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject> holder, 28093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 28103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 28113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_dont_delete) { 2812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -- r0 : receiver 2814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 2815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the global has not changed. 28203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(r0, &miss); 28213bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CheckPrototypes(object, r0, holder, r3, r4, r1, name, &miss); 2822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the value from the cell. 28243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r3, Operand(cell)); 28256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ldr(r4, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); 2826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for deleted property if property can actually be deleted. 2828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!is_dont_delete) { 2829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 28306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(r4, ip); 2831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &miss); 2832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r0, r4); 283544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = masm()->isolate()->counters(); 283644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3); 2837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Ret(); 2838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 284044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_load_global_stub_miss(), 1, r1, r3); 2841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(NORMAL, name); 2845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28483ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name, 28493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 28503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 28515913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index) { 2852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 28546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- r0 : key 285525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // -- r1 : receiver 2856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check the key is the cached one. 28603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r0, Operand(name)); 2861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 2862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28633bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch GenerateLoadField(receiver, holder, r1, r2, r3, r4, index, name, &miss); 2864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(FIELD, name); 2868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28713ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadCallback( 28723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 28733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 28743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 28753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback) { 2876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 28786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- r0 : key 287925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // -- r1 : receiver 2880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check the key is the cached one. 28843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r0, Operand(name)); 2885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 2886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadCallback(receiver, holder, r1, r0, r2, r3, r4, callback, name, 28883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 2889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28963ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadConstant( 28973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 28983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 28993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 29003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> value) { 2901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 29036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- r0 : key 290425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // -- r1 : receiver 2905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check the key is the cached one. 29093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r0, Operand(name)); 2910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 2911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29123bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch GenerateLoadConstant(receiver, holder, r1, r2, r3, r4, value, name, &miss); 2913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CONSTANT_FUNCTION, name); 2918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29213ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor( 29223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 29233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 29243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 29276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- r0 : key 292825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // -- r1 : receiver 2929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check the key is the cached one. 29333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r0, Operand(name)); 2934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 2935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 29374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke LookupPostInterceptor(holder, name, &lookup); 29383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadInterceptor(receiver, holder, &lookup, r1, r0, r2, r3, r4, name, 2939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &miss); 2940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29473ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength( 29483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 29516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- r0 : key 295225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // -- r1 : receiver 2953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check the key is the cached one. 29573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r0, Operand(name)); 2958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 2959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GenerateLoadArrayLength(masm(), r1, r2, &miss); 2961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29683ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadStringLength( 29693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 29726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- r0 : key 297325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // -- r1 : receiver 2974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 297644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 297744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = masm()->isolate()->counters(); 297844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_string_length(), 1, r2, r3); 2979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check the key is the cached one. 29813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r0, Operand(name)); 2982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 2983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block GenerateLoadStringLength(masm(), r1, r2, r3, &miss, true); 2985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 298644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_string_length(), 1, r2, r3); 2987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29943ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype( 29953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 29986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- r0 : key 299925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // -- r1 : receiver 3000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 30018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label miss; 30028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 300344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = masm()->isolate()->counters(); 300444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_function_prototype(), 1, r2, r3); 30058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 30068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check the name hasn't changed. 30073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r0, Operand(name)); 30088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(ne, &miss); 30098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 30108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GenerateLoadFunctionPrototype(masm(), r1, r2, r3, &miss); 30118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&miss); 301244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_function_prototype(), 1, r2, r3); 3013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 3016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30193ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadElement( 30203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> receiver_map) { 3021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------- S t a t e ------------- 3022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- lr : return address 3023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- r0 : key 3024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- r1 : receiver 3025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------------------------------- 3026589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind = receiver_map->elements_kind(); 30273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode(); 30283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DispatchMap(r1, r2, receiver_map, stub, DO_SMI_CHECK); 3030257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3031257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); 3032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(ic, RelocInfo::CODE_TARGET); 3033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 30353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string()); 3036257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 30393ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( 30403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MapHandleList* receiver_maps, 30413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CodeHandleList* handler_ics) { 3042257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3043257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- lr : return address 3044257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r0 : key 3045257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r1 : receiver 3046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 3048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(r1, &miss); 3049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3050257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int receiver_count = receiver_maps->length(); 3051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); 3052257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int current = 0; current < receiver_count; ++current) { 30533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ip, Operand(receiver_maps->at(current))); 3054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(r2, ip); 30553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(handler_ics->at(current), RelocInfo::CODE_TARGET, eq); 3056257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&miss); 3059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> miss_ic = isolate()->builtins()->KeyedLoadIC_Miss(); 3060257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(miss_ic, RelocInfo::CODE_TARGET, al); 3061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Return the generated code. 30633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); 3064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 30673ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object, 30685913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index, 30693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> transition, 30703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 3071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 3072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : value 3073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- r1 : name 3074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -- r2 : receiver 3075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 3076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 3077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 3078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 307944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = masm()->isolate()->counters(); 308044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_store_field(), 1, r3, r4); 3081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 30833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r1, Operand(name)); 3084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 3085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // r3 is used as scratch register. r1 and r2 keep their values if a jump to 3087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // the miss label is generated. 30883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateStoreField(masm(), object, index, transition, r2, r1, r3, &miss); 3089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 3090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 309144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_store_field(), 1, r3, r4); 309244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss(); 3093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 3094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 30963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); 3097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 31003ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreElement( 31013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> receiver_map) { 3102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------- S t a t e ------------- 3103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- r0 : value 3104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- r1 : key 3105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- r2 : receiver 3106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- lr : return address 3107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- r3 : scratch 3108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------------------------------- 3109589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind = receiver_map->elements_kind(); 3110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; 31113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> stub = 31123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch KeyedStoreElementStub(is_js_array, elements_kind, grow_mode_).GetCode(); 31133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 31143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DispatchMap(r2, r3, receiver_map, stub, DO_SMI_CHECK); 3115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 3117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(ic, RelocInfo::CODE_TARGET); 3118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 31203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string()); 3121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 31243ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( 31253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MapHandleList* receiver_maps, 31263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CodeHandleList* handler_stubs, 31273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MapHandleList* transitioned_maps) { 3128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r0 : value 3130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r1 : key 3131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r2 : receiver 3132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- lr : return address 3133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r3 : scratch 3134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 3136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(r2, &miss); 3137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int receiver_count = receiver_maps->length(); 3139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldr(r3, FieldMemOperand(r2, HeapObject::kMapOffset)); 31403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < receiver_count; ++i) { 31413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ip, Operand(receiver_maps->at(i))); 3142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(r3, ip); 31433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (transitioned_maps->at(i).is_null()) { 31443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, eq); 31453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 31463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label next_map; 31473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &next_map); 31483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r3, Operand(transitioned_maps->at(i))); 31493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, al); 31503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&next_map); 31513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&miss); 3155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss(); 3156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(miss_ic, RelocInfo::CODE_TARGET, al); 3157e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3158e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Return the generated code. 31593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); 3160e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 3161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3162e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 31633ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> ConstructStubCompiler::CompileConstructStub( 31643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function) { 3165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 3166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : argc 3167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r1 : constructor 3168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 3169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- [sp] : last argument 3170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 3171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label generic_stub_call; 3172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use r7 for holding undefined which is used in several places below. 3174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(r7, Heap::kUndefinedValueRootIndex); 3175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 3177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check to see whether there are any break points in the function code. If 3178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // there are jump to the generic constructor stub which calls the actual 3179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // code for the function thereby hitting the break points. 3180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 3181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kDebugInfoOffset)); 3182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, r7); 3183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &generic_stub_call); 3184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 3185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the initial map and verify that it is in fact a map. 3187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 3188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 3189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 31903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(r2, &generic_stub_call); 3191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(r2, r3, r4, MAP_TYPE); 3192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &generic_stub_call); 3193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 3195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cannot construct functions this way. 3196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 3197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 3198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: initial map 3199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 3200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE); 3201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Check(ne, "Function constructed by construct stub."); 3202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 3203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Now allocate the JSObject in new space. 3205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 3206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 3207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: initial map 3208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 3209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset)); 32103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(r3, r4, r5, r6, &generic_stub_call, SIZE_IN_WORDS); 3211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocated the JSObject, now initialize the fields. Map is set to initial 3213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // map and properties and elements are set to empty fixed array. 3214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 3215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 3216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: initial map 3217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: object size (in words) 3218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject (not tagged) 3219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 3220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex); 3221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r5, r4); 3222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); 3223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r2, MemOperand(r5, kPointerSize, PostIndex)); 3224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset); 3225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); 3226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset); 3227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); 3228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the location of the first argument. The stack contains only the 3230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // argc arguments. 3231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r1, sp, Operand(r0, LSL, kPointerSizeLog2)); 3232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill all the in-object properties with undefined. 3234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 3235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: first argument 3236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: object size (in words) 3237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject (not tagged) 3238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r5: First in-object property of JSObject (not tagged) 3239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 3240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the initialized properties with a constant value or a passed argument 3241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // depending on the this.x = ...; assignment in the function. 32423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<SharedFunctionInfo> shared(function->shared()); 3243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < shared->this_property_assignments_count(); i++) { 3244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (shared->IsThisPropertyAssignmentArgument(i)) { 3245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label not_passed, next; 3246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the argument assigned to the property is actually passed. 3247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int arg_number = shared->GetThisPropertyAssignmentArgument(i); 3248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, Operand(arg_number)); 3249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(le, ¬_passed); 3250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Argument passed - find it on the stack. 3251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, MemOperand(r1, (arg_number + 1) * -kPointerSize)); 3252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r2, MemOperand(r5, kPointerSize, PostIndex)); 3253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(&next); 3254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(¬_passed); 3255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the property to undefined. 3256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r7, MemOperand(r5, kPointerSize, PostIndex)); 3257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&next); 3258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 3259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the property to the constant value. 3260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i)); 3261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, Operand(constant)); 3262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r2, MemOperand(r5, kPointerSize, PostIndex)); 3263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the unused in-object property fields with undefined. 32678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ASSERT(function->has_initial_map()); 3268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = shared->this_property_assignments_count(); 32698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang i < function->initial_map()->inobject_properties(); 3270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i++) { 3271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r7, MemOperand(r5, kPointerSize, PostIndex)); 3272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 3275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject (not tagged) 3276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move argc to r1 and the JSObject to return to r0 and tag it. 3277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r1, r0); 3278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, r4); 3279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ orr(r0, r0, Operand(kHeapObjectTag)); 3280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: JSObject 3282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: argc 3283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Remove caller arguments and receiver from the stack and return. 3284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2)); 3285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(kPointerSize)); 328644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = masm()->isolate()->counters(); 328744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->constructed_objects(), 1, r1, r2); 328844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->constructed_objects_stub(), 1, r1, r2); 3289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 3290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the generic stub in case the specialized code cannot handle the 3292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // construction. 3293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&generic_stub_call); 329444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> code = masm()->isolate()->builtins()->JSConstructStubGeneric(); 329544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Jump(code, RelocInfo::CODE_TARGET); 3296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 3298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(); 3299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 33023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#undef __ 33033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#define __ ACCESS_MASM(masm) 33043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 33053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 33063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadDictionaryElement( 33073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MacroAssembler* masm) { 33083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ---------- S t a t e -------------- 33093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- lr : return address 33103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r0 : key 33113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r1 : receiver 3312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 33133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label slow, miss_force_generic; 3314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 33153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register key = r0; 33163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register receiver = r1; 3317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 33183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(key, &miss_force_generic); 33193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(r2, Operand(key, ASR, kSmiTagSize)); 33203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset)); 33213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ LoadFromNumberDictionary(&slow, r4, key, r0, r2, r3, r5); 33223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Ret(); 3323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 33243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&slow); 33253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ IncrementCounter( 33263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->counters()->keyed_load_external_array_slow(), 33273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1, r2, r3); 3328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 33293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ---------- S t a t e -------------- 33303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- lr : return address 33313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r0 : key 33323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r1 : receiver 3333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 33343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> slow_ic = 33353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_Slow(); 33363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Jump(slow_ic, RelocInfo::CODE_TARGET); 3337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 33383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Miss case, call the runtime. 33393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&miss_force_generic); 3340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 33413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ---------- S t a t e -------------- 33423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- lr : return address 33433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r0 : key 33443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r1 : receiver 33453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------------------------------- 3346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 33473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> miss_ic = 33483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 33493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Jump(miss_ic, RelocInfo::CODE_TARGET); 33503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 3351257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3352257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3353589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochstatic bool IsElementTypeSigned(ElementsKind elements_kind) { 33543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3355589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 3356589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 3357589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 33581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return true; 33591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3360589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 3361589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 3362589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 3363589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 33641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return false; 33651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3366589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 3367589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 3368589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_ELEMENTS: 33693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_SMI_ONLY_ELEMENTS: 3370589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_DOUBLE_ELEMENTS: 3371589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case DICTIONARY_ELEMENTS: 3372589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case NON_STRICT_ARGUMENTS_ELEMENTS: 33731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 33741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return false; 33751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 33763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return false; 33771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 33781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadExternalArray( 3381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MacroAssembler* masm, 3382589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind) { 33831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ---------- S t a t e -------------- 33841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- lr : return address 33851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- r0 : key 33861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- r1 : receiver 33871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 3388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss_force_generic, slow, failed_allocation; 33891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register key = r0; 33911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register receiver = r1; 33921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 3394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 33951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the key is a smi. 3397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(key, &miss_force_generic); 33981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset)); 340044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // r3: elements array 34011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the index is in range. 34031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset)); 340469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmp(key, ip); 34051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Unsigned comparison catches both negative and too-large values. 340669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ b(hs, &miss_force_generic); 34071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); 34091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // r3: base pointer of external storage 34101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // We are not untagging smi key and instead work with it 34121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // as if it was premultiplied by 2. 341369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT((kSmiTag == 0) && (kSmiTagSize == 1)); 34141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register value = r2; 34163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3417589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 34181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldrsb(value, MemOperand(r3, key, LSR, 1)); 34191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3420589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 3421589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 34221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldrb(value, MemOperand(r3, key, LSR, 1)); 34231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3424589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 34251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldrsh(value, MemOperand(r3, key, LSL, 0)); 34261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3427589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 34281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldrh(value, MemOperand(r3, key, LSL, 0)); 34291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3430589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 3431589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 34321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldr(value, MemOperand(r3, key, LSL, 1)); 34331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3434589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 34358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CpuFeatures::IsSupported(VFP3)) { 34361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CpuFeatures::Scope scope(VFP3); 34371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ add(r2, r3, Operand(key, LSL, 1)); 34381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ vldr(s0, r2, 0); 34391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 34401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldr(value, MemOperand(r3, key, LSL, 1)); 34411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 34421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3443589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 3444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(VFP3)) { 3445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(VFP3); 3446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ add(r2, r3, Operand(key, LSL, 2)); 3447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ vldr(d0, r2, 0); 3448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ add(r4, r3, Operand(key, LSL, 2)); 3450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // r4: pointer to the beginning of the double we want to load. 3451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldr(r2, MemOperand(r4, 0)); 3452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldr(r3, MemOperand(r4, Register::kSizeInBytes)); 3453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3455589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_ELEMENTS: 34563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_SMI_ONLY_ELEMENTS: 3457589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_DOUBLE_ELEMENTS: 3458589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case DICTIONARY_ELEMENTS: 3459589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case NON_STRICT_ARGUMENTS_ELEMENTS: 34601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 34611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 34621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 34631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For integer array types: 34651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // r2: value 3466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // For float array type: 34671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // s0: value (if VFP3 is supported) 34681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // r2: value (if VFP3 is not supported) 3469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // For double array type: 3470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // d0: value (if VFP3 is supported) 3471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // r2/r3: value (if VFP3 is not supported) 34721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3473589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_INT_ELEMENTS) { 34741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For the Int and UnsignedInt array types, we need to see whether 34751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the value can be represented in a Smi. If not, we need to convert 34761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // it to a HeapNumber. 34771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label box_int; 34781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmp(value, Operand(0xC0000000)); 34791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(mi, &box_int); 34801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Tag integer as smi and return it. 34811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(r0, Operand(value, LSL, kSmiTagSize)); 34821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(); 34831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&box_int); 34851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Allocate a HeapNumber for the result and perform int-to-double 34861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // conversion. Don't touch r0 or r1 as they are needed if allocation 34871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // fails. 34881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); 34891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ AllocateHeapNumber(r5, r3, r4, r6, &slow); 34901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Now we can use r0 for the result as key is not needed any more. 34911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(r0, r5); 34921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CpuFeatures::IsSupported(VFP3)) { 34941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CpuFeatures::Scope scope(VFP3); 34951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ vmov(s0, value); 34961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ vcvt_f64_s32(d0, s0); 34971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ sub(r3, r0, Operand(kHeapObjectTag)); 34981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ vstr(d0, r3, HeapNumber::kValueOffset); 34991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(); 35001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 3501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register dst1 = r1; 3502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register dst2 = r3; 3503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FloatingPointHelper::Destination dest = 3504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FloatingPointHelper::kCoreRegisters; 3505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FloatingPointHelper::ConvertIntToDouble(masm, 3506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch value, 3507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch dest, 3508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch d0, 3509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch dst1, 3510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch dst2, 3511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch r9, 3512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch s0); 3513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ str(dst1, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); 3514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ str(dst2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); 3515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 35161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 3517589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { 35181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // The test is different for unsigned int values. Since we need 35191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the value to be in the range of a positive smi, we can't 35201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // handle either of the top two bits being set in the value. 35218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CpuFeatures::IsSupported(VFP3)) { 35221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CpuFeatures::Scope scope(VFP3); 35231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label box_int, done; 35241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ tst(value, Operand(0xC0000000)); 35251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(ne, &box_int); 35261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Tag integer as smi and return it. 35271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(r0, Operand(value, LSL, kSmiTagSize)); 35281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(); 35291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&box_int); 35311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ vmov(s0, value); 35321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Allocate a HeapNumber for the result and perform int-to-double 35331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // conversion. Don't use r0 and r1 as AllocateHeapNumber clobbers all 35341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // registers - also when jumping due to exhausted young space. 35351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); 35361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ AllocateHeapNumber(r2, r3, r4, r6, &slow); 35371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ vcvt_f64_u32(d0, s0); 35391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ sub(r1, r2, Operand(kHeapObjectTag)); 35401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ vstr(d0, r1, HeapNumber::kValueOffset); 35411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(r0, r2); 35431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(); 35441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 35451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check whether unsigned integer fits into smi. 35461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label box_int_0, box_int_1, done; 35471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ tst(value, Operand(0x80000000)); 35481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(ne, &box_int_0); 35491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ tst(value, Operand(0x40000000)); 35501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(ne, &box_int_1); 35511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Tag integer as smi and return it. 35521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(r0, Operand(value, LSL, kSmiTagSize)); 35531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(); 35541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register hiword = value; // r2. 35561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register loword = r3; 35571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&box_int_0); 35591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Integer does not have leading zeros. 3560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateUInt2Double(masm, hiword, loword, r4, 0); 35611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(&done); 35621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&box_int_1); 35641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Integer has one leading zero. 3565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateUInt2Double(masm, hiword, loword, r4, 1); 35661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&done); 35691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Integer was converted to double in registers hiword:loword. 35701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Wrap it into a HeapNumber. Don't use r0 and r1 as AllocateHeapNumber 35711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // clobbers all registers - also when jumping due to exhausted young 35721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // space. 35731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); 35741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ AllocateHeapNumber(r4, r5, r7, r6, &slow); 35751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ str(hiword, FieldMemOperand(r4, HeapNumber::kExponentOffset)); 35771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ str(loword, FieldMemOperand(r4, HeapNumber::kMantissaOffset)); 35781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(r0, r4); 35801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(); 35811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 3582589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 35831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For the floating-point array type, we need to always allocate a 35841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // HeapNumber. 35858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CpuFeatures::IsSupported(VFP3)) { 35861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CpuFeatures::Scope scope(VFP3); 35871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Allocate a HeapNumber for the result. Don't use r0 and r1 as 35881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // AllocateHeapNumber clobbers all registers - also when jumping due to 35891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // exhausted young space. 35901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); 35911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ AllocateHeapNumber(r2, r3, r4, r6, &slow); 35921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ vcvt_f64_f32(d0, s0); 35931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ sub(r1, r2, Operand(kHeapObjectTag)); 35941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ vstr(d0, r1, HeapNumber::kValueOffset); 35951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(r0, r2); 35971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(); 35981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 35991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Allocate a HeapNumber for the result. Don't use r0 and r1 as 36001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // AllocateHeapNumber clobbers all registers - also when jumping due to 36011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // exhausted young space. 36021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); 36031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ AllocateHeapNumber(r3, r4, r5, r6, &slow); 36041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // VFP is not available, do manual single to double conversion. 36051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // r2: floating point value (binary32) 36071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // r3: heap number for result 36081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Extract mantissa to r0. OK to clobber r0 now as there are no jumps to 36101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the slow case from here. 36111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ and_(r0, value, Operand(kBinary32MantissaMask)); 36121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Extract exponent to r1. OK to clobber r1 now as there are no jumps to 36141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the slow case from here. 36151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(r1, Operand(value, LSR, kBinary32MantissaBits)); 36161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ and_(r1, r1, Operand(kBinary32ExponentMask >> kBinary32MantissaBits)); 36171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label exponent_rebiased; 36191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ teq(r1, Operand(0x00)); 36201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(eq, &exponent_rebiased); 36211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ teq(r1, Operand(0xff)); 36231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(r1, Operand(0x7ff), LeaveCC, eq); 36241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(eq, &exponent_rebiased); 36251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Rebias exponent. 36271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ add(r1, 36281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block r1, 36291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Operand(-kBinary32ExponentBias + HeapNumber::kExponentBias)); 36301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&exponent_rebiased); 36321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ and_(r2, value, Operand(kBinary32SignMask)); 36331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block value = no_reg; 36341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ orr(r2, r2, Operand(r1, LSL, HeapNumber::kMantissaBitsInTopWord)); 36351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Shift mantissa. 36371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block static const int kMantissaShiftForHiWord = 36381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord; 36391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block static const int kMantissaShiftForLoWord = 36411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block kBitsPerInt - kMantissaShiftForHiWord; 36421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ orr(r2, r2, Operand(r0, LSR, kMantissaShiftForHiWord)); 36441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(r0, Operand(r0, LSL, kMantissaShiftForLoWord)); 36451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ str(r2, FieldMemOperand(r3, HeapNumber::kExponentOffset)); 36471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ str(r0, FieldMemOperand(r3, HeapNumber::kMantissaOffset)); 36481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(r0, r3); 36501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(); 36511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 3652589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 3653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(VFP3)) { 3654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(VFP3); 3655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Allocate a HeapNumber for the result. Don't use r0 and r1 as 3656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // AllocateHeapNumber clobbers all registers - also when jumping due to 3657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // exhausted young space. 3658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); 3659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AllocateHeapNumber(r2, r3, r4, r6, &slow); 3660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sub(r1, r2, Operand(kHeapObjectTag)); 3661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ vstr(d0, r1, HeapNumber::kValueOffset); 3662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(r0, r2); 3664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 3665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Allocate a HeapNumber for the result. Don't use r0 and r1 as 3667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // AllocateHeapNumber clobbers all registers - also when jumping due to 3668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // exhausted young space. 3669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(r7, Heap::kHeapNumberMapRootIndex); 3670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AllocateHeapNumber(r4, r5, r6, r7, &slow); 3671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ str(r2, FieldMemOperand(r4, HeapNumber::kMantissaOffset)); 3673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ str(r3, FieldMemOperand(r4, HeapNumber::kExponentOffset)); 3674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(r0, r4); 3675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 3676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 36771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 36791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Tag integer as smi and return it. 36801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(r0, Operand(value, LSL, kSmiTagSize)); 36811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(); 36821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 36831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Slow case, key and receiver still in r0 and r1. 36851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&slow); 368644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter( 3687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->counters()->keyed_load_external_array_slow(), 368844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1, r2, r3); 36891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ---------- S t a t e -------------- 36911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- lr : return address 36921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- r0 : key 36931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- r1 : receiver 36941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 36951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Push(r1, r0); 36971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 36991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 37013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> stub = 37023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 37033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(stub, RelocInfo::CODE_TARGET); 37041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 37051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreExternalArray( 3708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MacroAssembler* masm, 3709589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind) { 37101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ---------- S t a t e -------------- 37111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- r0 : value 37121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- r1 : key 37131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- r2 : receiver 37141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- lr : return address 37151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 3716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label slow, check_heap_number, miss_force_generic; 37171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Register usage. 37191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register value = r0; 37201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register key = r1; 37211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register receiver = r2; 37221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // r3 mostly holds the elements array or the destination external array. 37231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 3725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 37261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the key is a smi. 3728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(key, &miss_force_generic); 37291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 373069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset)); 373169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 373244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the index is in range 37331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset)); 373469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmp(key, ip); 37351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Unsigned comparison catches both negative and too-large values. 3736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ b(hs, &miss_force_generic); 37371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Handle both smis and HeapNumbers in the fast path. Go to the 37391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // runtime for all other kinds of values. 37401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // r3: external array. 3741589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) { 374244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Double to pixel conversion is only implemented in the runtime for now. 374344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ JumpIfNotSmi(value, &slow); 374444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 374544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ JumpIfNotSmi(value, &check_heap_number); 374644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 374744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ SmiUntag(r5, value); 37481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); 37491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // r3: base pointer of external storage. 37511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // r5: value (integer). 37523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3753589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 375444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Clamp the value to [0..255]. 375544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Usat(r5, 8, Operand(r5)); 375669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ strb(r5, MemOperand(r3, key, LSR, 1)); 375744f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3758589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 3759589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 376069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ strb(r5, MemOperand(r3, key, LSR, 1)); 37611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3762589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 3763589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 376469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ strh(r5, MemOperand(r3, key, LSL, 0)); 37651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3766589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 3767589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 376869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ str(r5, MemOperand(r3, key, LSL, 1)); 37691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3770589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 37711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Perform int-to-float conversion and store to memory. 377269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ SmiUntag(r4, key); 3773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StoreIntAsFloat(masm, r3, r4, r5, r6, r7, r9); 3774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3775589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 377669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ add(r3, r3, Operand(key, LSL, 2)); 3777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // r3: effective address of the double element 3778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FloatingPointHelper::Destination destination; 3779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(VFP3)) { 3780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch destination = FloatingPointHelper::kVFPRegisters; 3781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch destination = FloatingPointHelper::kCoreRegisters; 3783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FloatingPointHelper::ConvertIntToDouble( 3785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm, r5, destination, 3786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch d0, r6, r7, // These are: double_dst, dst1, dst2. 3787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch r4, s2); // These are: scratch2, single_scratch. 3788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (destination == FloatingPointHelper::kVFPRegisters) { 3789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(VFP3); 3790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ vstr(d0, r3, 0); 3791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ str(r6, MemOperand(r3, 0)); 3793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ str(r7, MemOperand(r3, Register::kSizeInBytes)); 3794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 37951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3796589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_ELEMENTS: 37973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_SMI_ONLY_ELEMENTS: 3798589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_DOUBLE_ELEMENTS: 3799589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case DICTIONARY_ELEMENTS: 3800589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case NON_STRICT_ARGUMENTS_ELEMENTS: 38011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 38021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 38031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 38041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 38051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Entry registers are intact, r0 holds the value which is the return value. 38061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(); 38071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3808589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) { 380944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // r3: external array. 381044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&check_heap_number); 381144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CompareObjectType(value, r5, r6, HEAP_NUMBER_TYPE); 381244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ b(ne, &slow); 38131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 381444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); 38151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 381644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // r3: base pointer of external storage. 38171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 381844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // The WebGL specification leaves the behavior of storing NaN and 381944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // +/-Infinity into integer arrays basically undefined. For more 382044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // reproducible behavior, convert these to zero. 38218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CpuFeatures::IsSupported(VFP3)) { 382244f0eee88ff00398ff7f715fab053374d808c90dSteve Block CpuFeatures::Scope scope(VFP3); 38231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3824589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 382544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // vldr requires offset to be a multiple of 4 so we can not 382644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // include -kHeapObjectTag into it. 382744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ sub(r5, r0, Operand(kHeapObjectTag)); 382844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ vldr(d0, r5, HeapNumber::kValueOffset); 382969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ add(r5, r3, Operand(key, LSL, 1)); 383044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ vcvt_f32_f64(s0, d0); 383144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ vstr(s0, r5, 0); 3832589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 3833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sub(r5, r0, Operand(kHeapObjectTag)); 3834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ vldr(d0, r5, HeapNumber::kValueOffset); 383569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ add(r5, r3, Operand(key, LSL, 2)); 3836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ vstr(d0, r5, 0); 38371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 383844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Hoisted load. vldr requires offset to be a multiple of 4 so we can 383944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // not include -kHeapObjectTag into it. 384044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ sub(r5, value, Operand(kHeapObjectTag)); 384144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ vldr(d0, r5, HeapNumber::kValueOffset); 38423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ EmitECMATruncate(r5, d0, s2, r6, r7, r9); 384344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 38443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3845589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 3846589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 384769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ strb(r5, MemOperand(r3, key, LSR, 1)); 384844f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3849589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 3850589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 385169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ strh(r5, MemOperand(r3, key, LSL, 0)); 385244f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3853589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 3854589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 385569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ str(r5, MemOperand(r3, key, LSL, 1)); 385644f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3857589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 3858589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 3859589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 3860589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_ELEMENTS: 38613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_SMI_ONLY_ELEMENTS: 3862589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_DOUBLE_ELEMENTS: 3863589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case DICTIONARY_ELEMENTS: 3864589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case NON_STRICT_ARGUMENTS_ELEMENTS: 386544f0eee88ff00398ff7f715fab053374d808c90dSteve Block UNREACHABLE(); 386644f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 386744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 38681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 38691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 38701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Entry registers are intact, r0 holds the value which is the return 38711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // value. 38721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(); 38731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 387444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // VFP3 is not available do manual conversions. 387544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ ldr(r5, FieldMemOperand(value, HeapNumber::kExponentOffset)); 387644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ ldr(r6, FieldMemOperand(value, HeapNumber::kMantissaOffset)); 387744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3878589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 387944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label done, nan_or_infinity_or_zero; 388044f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const int kMantissaInHiWordShift = 388144f0eee88ff00398ff7f715fab053374d808c90dSteve Block kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord; 388244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 388344f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const int kMantissaInLoWordShift = 388444f0eee88ff00398ff7f715fab053374d808c90dSteve Block kBitsPerInt - kMantissaInHiWordShift; 388544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 388644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Test for all special exponent values: zeros, subnormal numbers, NaNs 388744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // and infinities. All these should be converted to 0. 388844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(r7, Operand(HeapNumber::kExponentMask)); 388944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ and_(r9, r5, Operand(r7), SetCC); 389044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ b(eq, &nan_or_infinity_or_zero); 389144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 389244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ teq(r9, Operand(r7)); 389344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(r9, Operand(kBinary32ExponentMask), LeaveCC, eq); 389444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ b(eq, &nan_or_infinity_or_zero); 389544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 389644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Rebias exponent. 389744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(r9, Operand(r9, LSR, HeapNumber::kExponentShift)); 389844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ add(r9, 389944f0eee88ff00398ff7f715fab053374d808c90dSteve Block r9, 390044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Operand(kBinary32ExponentBias - HeapNumber::kExponentBias)); 390144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 390244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(r9, Operand(kBinary32MaxExponent)); 390344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ and_(r5, r5, Operand(HeapNumber::kSignMask), LeaveCC, gt); 390444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ orr(r5, r5, Operand(kBinary32ExponentMask), LeaveCC, gt); 390544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ b(gt, &done); 390644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 390744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(r9, Operand(kBinary32MinExponent)); 390844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ and_(r5, r5, Operand(HeapNumber::kSignMask), LeaveCC, lt); 390944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ b(lt, &done); 391044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 391144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ and_(r7, r5, Operand(HeapNumber::kSignMask)); 391244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ and_(r5, r5, Operand(HeapNumber::kMantissaMask)); 391344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ orr(r7, r7, Operand(r5, LSL, kMantissaInHiWordShift)); 391444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ orr(r7, r7, Operand(r6, LSR, kMantissaInLoWordShift)); 391544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ orr(r5, r7, Operand(r9, LSL, kBinary32ExponentShift)); 391644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 391744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&done); 391869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ str(r5, MemOperand(r3, key, LSL, 1)); 391944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Entry registers are intact, r0 holds the value which is the return 392044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // value. 392144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Ret(); 392244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 392344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&nan_or_infinity_or_zero); 392444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ and_(r7, r5, Operand(HeapNumber::kSignMask)); 392544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ and_(r5, r5, Operand(HeapNumber::kMantissaMask)); 392644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ orr(r9, r9, r7); 392744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ orr(r9, r9, Operand(r5, LSL, kMantissaInHiWordShift)); 392844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ orr(r5, r9, Operand(r6, LSR, kMantissaInLoWordShift)); 392944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ b(&done); 3930589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 393169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ add(r7, r3, Operand(key, LSL, 2)); 3932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // r7: effective address of destination element. 3933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ str(r6, MemOperand(r7, 0)); 3934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ str(r5, MemOperand(r7, Register::kSizeInBytes)); 3935257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 393644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 39373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool is_signed_type = IsElementTypeSigned(elements_kind); 393844f0eee88ff00398ff7f715fab053374d808c90dSteve Block int meaningfull_bits = is_signed_type ? (kBitsPerInt - 1) : kBitsPerInt; 393944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t min_value = is_signed_type ? 0x80000000 : 0x00000000; 394044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 394144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label done, sign; 394244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 394344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Test for all special exponent values: zeros, subnormal numbers, NaNs 394444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // and infinities. All these should be converted to 0. 394544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(r7, Operand(HeapNumber::kExponentMask)); 394644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ and_(r9, r5, Operand(r7), SetCC); 394744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq); 394844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ b(eq, &done); 394944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 395044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ teq(r9, Operand(r7)); 395144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq); 395244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ b(eq, &done); 395344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 395444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Unbias exponent. 395544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(r9, Operand(r9, LSR, HeapNumber::kExponentShift)); 395644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ sub(r9, r9, Operand(HeapNumber::kExponentBias), SetCC); 395744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // If exponent is negative then result is 0. 395844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, mi); 395944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ b(mi, &done); 396044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 396144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // If exponent is too big then result is minimal value. 396244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(r9, Operand(meaningfull_bits - 1)); 396344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(r5, Operand(min_value), LeaveCC, ge); 396444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ b(ge, &done); 396544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 396644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ and_(r7, r5, Operand(HeapNumber::kSignMask), SetCC); 396744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ and_(r5, r5, Operand(HeapNumber::kMantissaMask)); 396844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ orr(r5, r5, Operand(1u << HeapNumber::kMantissaBitsInTopWord)); 396944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 397044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ rsb(r9, r9, Operand(HeapNumber::kMantissaBitsInTopWord), SetCC); 397144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(r5, Operand(r5, LSR, r9), LeaveCC, pl); 397244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ b(pl, &sign); 397344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 397444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ rsb(r9, r9, Operand(0, RelocInfo::NONE)); 397544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(r5, Operand(r5, LSL, r9)); 397644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ rsb(r9, r9, Operand(meaningfull_bits)); 397744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ orr(r5, r5, Operand(r6, LSR, r9)); 397844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 397944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&sign); 398044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ teq(r7, Operand(0, RelocInfo::NONE)); 398144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ rsb(r5, r5, Operand(0, RelocInfo::NONE), LeaveCC, ne); 398244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 398344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&done); 39843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3985589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 3986589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 398769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ strb(r5, MemOperand(r3, key, LSR, 1)); 398844f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3989589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 3990589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 399169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ strh(r5, MemOperand(r3, key, LSL, 0)); 399244f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3993589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 3994589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 399569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ str(r5, MemOperand(r3, key, LSL, 1)); 399644f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3997589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 3998589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 3999589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 4000589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_ELEMENTS: 40013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_SMI_ONLY_ELEMENTS: 4002589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_DOUBLE_ELEMENTS: 4003589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case DICTIONARY_ELEMENTS: 4004589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case NON_STRICT_ARGUMENTS_ELEMENTS: 400544f0eee88ff00398ff7f715fab053374d808c90dSteve Block UNREACHABLE(); 400644f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 400744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 40081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 40091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 40101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 40111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 4012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Slow case, key and receiver still in r0 and r1. 40131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&slow); 4014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter( 4015257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->counters()->keyed_load_external_array_slow(), 4016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1, r2, r3); 40171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 40181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ---------- S t a t e -------------- 40191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- lr : return address 4020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r0 : key 4021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r1 : receiver 40221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 4023257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> slow_ic = 4024257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->builtins()->KeyedStoreIC_Slow(); 4025257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(slow_ic, RelocInfo::CODE_TARGET); 40261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 4027257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Miss case, call the runtime. 4028257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 40291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 4030257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ---------- S t a t e -------------- 4031257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- lr : return address 4032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r0 : key 4033257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r1 : receiver 4034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 4035257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4036257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> miss_ic = 4037257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 4038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(miss_ic, RelocInfo::CODE_TARGET); 4039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 4040257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4041257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4042257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) { 4043257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 4044257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- lr : return address 4045257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r0 : key 4046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r1 : receiver 4047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 4048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss_force_generic; 4049e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4050257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 4051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 40521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 4053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is a smi. 4054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(r0, &miss_force_generic); 4055257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4056257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the elements array. 4057257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldr(r2, FieldMemOperand(r1, JSObject::kElementsOffset)); 4058257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AssertFastElements(r2); 4059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4060257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is within bounds. 4061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldr(r3, FieldMemOperand(r2, FixedArray::kLengthOffset)); 4062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(r0, Operand(r3)); 4063257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ b(hs, &miss_force_generic); 4064257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4065257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the result and make sure it's not the hole. 4066257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ add(r3, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 406769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); 4068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldr(r4, 4069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MemOperand(r3, r0, LSL, kPointerSizeLog2 - kSmiTagSize)); 4070257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 4071257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(r4, ip); 4072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ b(eq, &miss_force_generic); 4073257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(r0, r4); 4074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 4075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 40773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> stub = 40783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 40793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(stub, RelocInfo::CODE_TARGET); 4080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 4081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4082257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 40833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastDoubleElement( 40843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MacroAssembler* masm) { 40853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------- S t a t e ------------- 40863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- lr : return address 40873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r0 : key 40883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r1 : receiver 40893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------------------------------- 40903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label miss_force_generic, slow_allocate_heapnumber; 40913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 40923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register key_reg = r0; 40933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register receiver_reg = r1; 40943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register elements_reg = r2; 40953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register heap_number_reg = r2; 40963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register indexed_double_offset = r3; 40973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register scratch = r4; 40983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register scratch2 = r5; 40993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register scratch3 = r6; 41003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register heap_number_map = r7; 41013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 41033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // have been verified by the caller to not be a smi. 41043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is a smi. 41063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(key_reg, &miss_force_generic); 41073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Get the elements array. 41093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ldr(elements_reg, 41103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 41113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is within bounds. 41133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ldr(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); 41143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp(key_reg, Operand(scratch)); 41153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ b(hs, &miss_force_generic); 41163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Load the upper word of the double in the fixed array and test for NaN. 41183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ add(indexed_double_offset, elements_reg, 41193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Operand(key_reg, LSL, kDoubleSizeLog2 - kSmiTagSize)); 41203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t upper_32_offset = FixedArray::kHeaderSize + sizeof(kHoleNanLower32); 41213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ldr(scratch, FieldMemOperand(indexed_double_offset, upper_32_offset)); 41223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp(scratch, Operand(kHoleNanUpper32)); 41233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ b(&miss_force_generic, eq); 41243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Non-NaN. Allocate a new heap number and copy the double value into it. 41263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); 41273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ AllocateHeapNumber(heap_number_reg, scratch2, scratch3, 41283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch heap_number_map, &slow_allocate_heapnumber); 41293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Don't need to reload the upper 32 bits of the double, it's already in 41313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // scratch. 41323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ str(scratch, FieldMemOperand(heap_number_reg, 41333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HeapNumber::kExponentOffset)); 41343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ldr(scratch, FieldMemOperand(indexed_double_offset, 41353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FixedArray::kHeaderSize)); 41363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ str(scratch, FieldMemOperand(heap_number_reg, 41373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HeapNumber::kMantissaOffset)); 41383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(r0, heap_number_reg); 41403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Ret(); 41413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&slow_allocate_heapnumber); 41433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> slow_ic = 41443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_Slow(); 41453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Jump(slow_ic, RelocInfo::CODE_TARGET); 41463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&miss_force_generic); 41483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> miss_ic = 41493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 41503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Jump(miss_ic, RelocInfo::CODE_TARGET); 41513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 41523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastElement( 41553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler* masm, 41563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_js_array, 41573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind elements_kind, 41583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch KeyedAccessGrowMode grow_mode) { 4159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 4160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r0 : value 4161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r1 : key 4162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r2 : receiver 4163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- lr : return address 4164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r3 : scratch 4165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r4 : scratch (elements) 4166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 41673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label miss_force_generic, transition_elements_kind, grow, slow; 41683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label finish_store, check_capacity; 4169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register value_reg = r0; 4171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register key_reg = r1; 4172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register receiver_reg = r2; 41733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch = r4; 41743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register elements_reg = r3; 41753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register length_reg = r5; 41763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch2 = r6; 4177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 4179257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 4180257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4181257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is a smi. 41823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(key_reg, &miss_force_generic); 4183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 41843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { 41853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfNotSmi(value_reg, &transition_elements_kind); 41863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 418785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 418885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // Check that the key is within bounds. 41893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(elements_reg, 41903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 4191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (is_js_array) { 4192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldr(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); 4193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 4194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldr(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); 4195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 4196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compare smis. 4197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(key_reg, scratch); 41983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) { 41993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(hs, &grow); 42003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 42013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(hs, &miss_force_generic); 42023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 42043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure elements is a fast element array, not 'cow'. 42053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(elements_reg, 42063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 42073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kFixedArrayMapRootIndex, 42083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss_force_generic, 42093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DONT_DO_SMI_CHECK); 42105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 42113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&finish_store); 42123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { 42133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(scratch, 42143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch elements_reg, 42153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 42163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); 42173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(scratch, 42183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 42193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand(key_reg, LSL, kPointerSizeLog2 - kSmiTagSize)); 42203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(value_reg, MemOperand(scratch)); 42213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 42223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(elements_kind == FAST_ELEMENTS); 42233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(scratch, 42243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch elements_reg, 42253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 42263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); 42273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(scratch, 42283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 42293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand(key_reg, LSL, kPointerSizeLog2 - kSmiTagSize)); 42303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(value_reg, MemOperand(scratch)); 42313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(receiver_reg, value_reg); 42323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWrite(elements_reg, // Object. 42333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, // Address. 42343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver_reg, // Value. 42353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kLRHasNotBeenSaved, 42363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs); 42373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // value_reg (r0) is preserved. 4239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Done. 4240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 4241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 4243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = 4244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 4245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(ic, RelocInfo::CODE_TARGET); 42463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&transition_elements_kind); 42483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); 42493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(ic_miss, RelocInfo::CODE_TARGET); 42503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) { 42523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Grow the array by a single element if possible. 42533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&grow); 42543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure the array is only growing by a single element, anything else 42563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // must be handled by the runtime. Flags already set by previous compare. 42573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &miss_force_generic); 42583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for the empty array, and preallocate a small backing store if 42603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // possible. 42613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(length_reg, 42623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); 42633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(elements_reg, 42643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 42653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(elements_reg, Heap::kEmptyFixedArrayRootIndex); 42663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &check_capacity); 42673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int size = FixedArray::SizeFor(JSArray::kPreallocatedArrayElements); 42693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(size, elements_reg, scratch, scratch2, &slow, 42703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TAG_OBJECT); 42713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(scratch, Heap::kFixedArrayMapRootIndex); 42733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(scratch, FieldMemOperand(elements_reg, JSObject::kMapOffset)); 42743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(scratch, Operand(Smi::FromInt(JSArray::kPreallocatedArrayElements))); 42753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); 42763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); 42773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 1; i < JSArray::kPreallocatedArrayElements; ++i) { 42783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(scratch, FieldMemOperand(elements_reg, FixedArray::SizeFor(i))); 42793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 42803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the element at index zero. 42823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(value_reg, FieldMemOperand(elements_reg, FixedArray::SizeFor(0))); 42833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Install the new backing store in the JSArray. 42853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(elements_reg, 42863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 42873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(receiver_reg, JSObject::kElementsOffset, elements_reg, 42883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, kLRHasNotBeenSaved, kDontSaveFPRegs, 42893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 42903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Increment the length of the array. 42923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(length_reg, Operand(Smi::FromInt(1))); 42933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); 42943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(); 42953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&check_capacity); 42973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for cow elements, in general they are not handled by this stub 42983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(elements_reg, 42993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 43003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kFixedCOWArrayMapRootIndex, 43013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss_force_generic, 43023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DONT_DO_SMI_CHECK); 43033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); 43053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(length_reg, scratch); 43063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(hs, &slow); 43073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Grow the array and finish the store. 43093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(length_reg, length_reg, Operand(Smi::FromInt(1))); 43103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); 43113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&finish_store); 43123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&slow); 43143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow(); 43153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(ic_slow, RelocInfo::CODE_TARGET); 43163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 43171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 43181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 43191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 43203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( 43213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MacroAssembler* masm, 43223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_js_array, 43233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch KeyedAccessGrowMode grow_mode) { 43243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------- S t a t e ------------- 43253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r0 : value 43263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r1 : key 43273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r2 : receiver 43283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- lr : return address 43293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r3 : scratch 43303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r4 : scratch 43313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r5 : scratch 43323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------------------------------- 43333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label miss_force_generic, transition_elements_kind, grow, slow; 43343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label finish_store, check_capacity; 43353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 43363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register value_reg = r0; 43373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register key_reg = r1; 43383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register receiver_reg = r2; 43393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register elements_reg = r3; 43403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1 = r4; 43413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch2 = r5; 43423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch3 = r6; 43433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register scratch4 = r7; 43443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register length_reg = r7; 43453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 43463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 43473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // have been verified by the caller to not be a smi. 43483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(key_reg, &miss_force_generic); 43493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 43503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ldr(elements_reg, 43513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 43523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 43533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is within bounds. 43543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (is_js_array) { 43553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(scratch1, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); 43563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 43573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(scratch1, 43583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); 43593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 43603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Compare smis, unsigned compare catches both negative and out-of-bound 43613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // indexes. 43623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(key_reg, scratch1); 43633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (grow_mode == ALLOW_JSARRAY_GROWTH) { 43643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(hs, &grow); 43655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } else { 43663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(hs, &miss_force_generic); 43675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 43683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 43693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&finish_store); 43703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ StoreNumberToDoubleElements(value_reg, 43713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch key_reg, 43723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver_reg, 43733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch elements_reg, 43743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, 43753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch2, 43763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch3, 43773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch4, 43783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &transition_elements_kind); 43793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Ret(); 43803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 43813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Handle store cache miss, replacing the ic with the generic stub. 43823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&miss_force_generic); 43833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> ic = 43843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 43853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Jump(ic, RelocInfo::CODE_TARGET); 43863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&transition_elements_kind); 43883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); 43893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(ic_miss, RelocInfo::CODE_TARGET); 43903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) { 43923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Grow the array by a single element if possible. 43933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&grow); 43943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure the array is only growing by a single element, anything else 43963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // must be handled by the runtime. Flags already set by previous compare. 43973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &miss_force_generic); 43983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Transition on values that can't be stored in a FixedDoubleArray. 44003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label value_is_smi; 44013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(value_reg, &value_is_smi); 44023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset)); 44033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(scratch1, Heap::kHeapNumberMapRootIndex); 44043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &transition_elements_kind); 44053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&value_is_smi); 44063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for the empty array, and preallocate a small backing store if 44083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // possible. 44093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(length_reg, 44103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); 44113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(elements_reg, 44123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 44133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(elements_reg, Heap::kEmptyFixedArrayRootIndex); 44143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &check_capacity); 44153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int size = FixedDoubleArray::SizeFor(JSArray::kPreallocatedArrayElements); 44173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(size, elements_reg, scratch1, scratch2, &slow, 44183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TAG_OBJECT); 44193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Initialize the new FixedDoubleArray. Leave elements unitialized for 44213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // efficiency, they are guaranteed to be initialized before use. 44223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(scratch1, Heap::kFixedDoubleArrayMapRootIndex); 44233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(scratch1, FieldMemOperand(elements_reg, JSObject::kMapOffset)); 44243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(scratch1, 44253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand(Smi::FromInt(JSArray::kPreallocatedArrayElements))); 44263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(scratch1, 44273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(elements_reg, FixedDoubleArray::kLengthOffset)); 44283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Install the new backing store in the JSArray. 44303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(elements_reg, 44313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 44323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(receiver_reg, JSObject::kElementsOffset, elements_reg, 44333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, kLRHasNotBeenSaved, kDontSaveFPRegs, 44343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 44353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Increment the length of the array. 44373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(length_reg, Operand(Smi::FromInt(1))); 44383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); 44399413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch __ ldr(elements_reg, 44409413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 44413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&finish_store); 44423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&check_capacity); 44443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure that the backing store can hold additional elements. 44453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(scratch1, 44463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(elements_reg, FixedDoubleArray::kLengthOffset)); 44473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(length_reg, scratch1); 44483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(hs, &slow); 44493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Grow the array and finish the store. 44513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(length_reg, length_reg, Operand(Smi::FromInt(1))); 44523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); 44533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&finish_store); 44543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&slow); 44563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow(); 44573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(ic_slow, RelocInfo::CODE_TARGET); 44583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 44593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 44603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 44613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 4463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 4465f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 4466f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_ARM 4467