stub-cache-arm.cc revision 8f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7
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 12697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Save necessary data before invoking an interceptor. 12707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Requires a frame to make GC aware of pushed pointers. 12713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 12723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope frame_scope(masm(), StackFrame::INTERNAL); 12733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { 12743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // CALLBACKS case needs a receiver to be passed into C++ callback. 12753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(receiver, holder_reg, name_reg); 12763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 12773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(holder_reg, name_reg); 12783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 12793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Invoke an interceptor. Note: map checks from receiver to 12803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // interceptor's holder has been compiled before (see a caller 12813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // of this method.) 12823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompileCallLoadPropertyWithInterceptor(masm(), 12833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver, 12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch holder_reg, 12853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name_reg, 12863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch interceptor_holder); 12873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if interceptor provided a value for property. If it's 12883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the case, return immediately. 12893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label interceptor_failed; 12903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex); 12913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r0, scratch1); 12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(eq, &interceptor_failed); 12933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch frame_scope.GenerateLeaveFrame(); 12943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(); 129585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 12963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&interceptor_failed); 12973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(name_reg); 12983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(holder_reg); 12993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { 13003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(receiver); 13013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 13023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Leave the internal frame. 130385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch } 13047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps from interceptor's holder to lookup's holder 13057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // haven't changed. And load lookup's holder into |holder| register. 13063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (*interceptor_holder != lookup->holder()) { 13077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch holder_reg = CheckPrototypes(interceptor_holder, 13087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch holder_reg, 13093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(lookup->holder()), 13107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch1, 13117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch scratch2, 13123bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch3, 13137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch name, 13147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch miss); 13157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 13167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (lookup->type() == FIELD) { 13187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // We found FIELD property in prototype chain of interceptor's holder. 13197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Retrieve a field from field's holder. 13207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateFastPropertyLoad(masm(), r0, holder_reg, 13213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(lookup->holder()), 13223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lookup->GetFieldIndex()); 13237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Ret(); 13247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 13257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // We found CALLBACKS property in prototype chain of interceptor's 13267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // holder. 13277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(lookup->type() == CALLBACKS); 13283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback( 13293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AccessorInfo::cast(lookup->GetCallbackObject())); 13307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(callback->getter() != NULL); 13317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Tail call to runtime. 13337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Important invariant in CALLBACKS case: the code above must be 13347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // structured to never clobber |receiver| register. 13353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(scratch2, callback); 13367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // holder_reg is either receiver or scratch1. 13377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (!receiver.is(holder_reg)) { 13387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(scratch1.is(holder_reg)); 13398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Push(receiver, holder_reg); 13408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(scratch3, 13418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang FieldMemOperand(scratch2, AccessorInfo::kDataOffset)); 13428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Push(scratch3, scratch2, name_reg); 13437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 13447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ push(receiver); 13458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(scratch3, 13468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang FieldMemOperand(scratch2, AccessorInfo::kDataOffset)); 13478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Push(holder_reg, scratch3, scratch2, name_reg); 13487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 13497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ExternalReference ref = 135144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kLoadCallbackProperty), 135244f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm()->isolate()); 13537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ TailCallExternalReference(ref, 5, 1); 13547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 13557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { // !compile_followup_inline 13567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Call the runtime system to load the interceptor. 13577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Check that the maps haven't changed. 13587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, 13593bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch scratch1, scratch2, scratch3, 13603bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch name, miss); 13617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch PushInterceptorArguments(masm(), receiver, holder_reg, 13627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch name_reg, interceptor_holder); 13637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 136444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference ref = 136544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), 136644f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm()->isolate()); 13677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ TailCallExternalReference(ref, 5, 1); 13687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { 13739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (kind_ == Code::KEYED_CALL_IC) { 13743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r2, Operand(name)); 13759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ b(ne, miss); 13769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 13779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 13789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 13799dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 13803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object, 13813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 13823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 138359151504615d929945dc59db37bf1166937748c6Steve Block Label* miss) { 138459151504615d929945dc59db37bf1166937748c6Steve Block ASSERT(holder->IsGlobalObject()); 138559151504615d929945dc59db37bf1166937748c6Steve Block 138659151504615d929945dc59db37bf1166937748c6Steve Block // Get the number of arguments. 138759151504615d929945dc59db37bf1166937748c6Steve Block const int argc = arguments().immediate(); 138859151504615d929945dc59db37bf1166937748c6Steve Block 138959151504615d929945dc59db37bf1166937748c6Steve Block // Get the receiver from the stack. 139059151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(r0, MemOperand(sp, argc * kPointerSize)); 139159151504615d929945dc59db37bf1166937748c6Steve Block 139259151504615d929945dc59db37bf1166937748c6Steve Block // Check that the maps haven't changed. 13933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(r0, miss); 139459151504615d929945dc59db37bf1166937748c6Steve Block CheckPrototypes(object, r0, holder, r3, r1, r4, name, miss); 139559151504615d929945dc59db37bf1166937748c6Steve Block} 139659151504615d929945dc59db37bf1166937748c6Steve Block 139759151504615d929945dc59db37bf1166937748c6Steve Block 13983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateLoadFunctionFromCell( 13993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 14003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 14013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 140259151504615d929945dc59db37bf1166937748c6Steve Block // Get the value from the cell. 14033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r3, Operand(cell)); 140459151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); 140559151504615d929945dc59db37bf1166937748c6Steve Block 140659151504615d929945dc59db37bf1166937748c6Steve Block // Check that the cell contains the same function. 14073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (heap()->InNewSpace(*function)) { 140859151504615d929945dc59db37bf1166937748c6Steve Block // We can't embed a pointer to a function in new space so we have 140959151504615d929945dc59db37bf1166937748c6Steve Block // to verify that the shared function info is unchanged. This has 141059151504615d929945dc59db37bf1166937748c6Steve Block // the nice side effect that multiple closures based on the same 141159151504615d929945dc59db37bf1166937748c6Steve Block // function can all use this call IC. Before we load through the 141259151504615d929945dc59db37bf1166937748c6Steve Block // function, we have to verify that it still is a function. 14133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(r1, miss); 141459151504615d929945dc59db37bf1166937748c6Steve Block __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); 141559151504615d929945dc59db37bf1166937748c6Steve Block __ b(ne, miss); 141659151504615d929945dc59db37bf1166937748c6Steve Block 141759151504615d929945dc59db37bf1166937748c6Steve Block // Check the shared function info. Make sure it hasn't changed. 141859151504615d929945dc59db37bf1166937748c6Steve Block __ Move(r3, Handle<SharedFunctionInfo>(function->shared())); 141959151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 142059151504615d929945dc59db37bf1166937748c6Steve Block __ cmp(r4, r3); 142159151504615d929945dc59db37bf1166937748c6Steve Block } else { 14223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r1, Operand(function)); 142359151504615d929945dc59db37bf1166937748c6Steve Block } 14243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, miss); 142559151504615d929945dc59db37bf1166937748c6Steve Block} 142659151504615d929945dc59db37bf1166937748c6Steve Block 142759151504615d929945dc59db37bf1166937748c6Steve Block 14283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateMissBranch() { 14293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = 1430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), 1431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch kind_, 14323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch extra_state_); 14333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(code, RelocInfo::CODE_TARGET); 14347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 14357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14373ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, 14383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 14395913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index, 14403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1442402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- r2 : name 1443402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- lr : return address 1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateNameCheck(name, &miss); 14489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 1450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver of the function from the stack into r0. 1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(sp, argc * kPointerSize)); 1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 14543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(r0, &miss); 1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do the right check and compute the holder register. 14573bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register reg = CheckPrototypes(object, r0, holder, r1, r3, r4, name, &miss); 1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateFastPropertyLoad(masm(), r1, reg, holder, index); 1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); 1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 14643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(FIELD, name); 1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14713ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPushCall( 14723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 14733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 14743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 14753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 14763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 14776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 14786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- r2 : name 14796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- lr : return address 14808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 14818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- ... 14828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- sp[argc * 4] : receiver 14836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 14846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 148559151504615d929945dc59db37bf1166937748c6Steve Block // If object is not an array, bail out to regular call. 14863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); 14876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss; 14899dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateNameCheck(name, &miss); 14909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 14918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register receiver = r1; 14926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the receiver from the stack 14936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int argc = arguments().immediate(); 14948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); 14956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the receiver isn't a smi. 14971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(receiver, &miss); 14986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the maps haven't changed. 15003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, r3, r0, r4, 15013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 15026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang if (argc == 0) { 15048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Nothing to do, just return the length. 15058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 15068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(argc + 1); 15078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 15088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } else { 15098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label call_builtin; 15108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 15113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (argc == 1) { // Otherwise fall through to call the builtin. 15123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label attempt_to_grow_elements; 15138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 15143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register elements = r6; 15153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register end_elements = r5; 15163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the elements array of the object. 15173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); 15185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 15193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that the elements are in fast mode and writable. 15203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(elements, 15213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r0, 15223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kFixedArrayMapRootIndex, 15233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &call_builtin, 15243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DONT_DO_SMI_CHECK); 15255d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 15265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 15278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Get the array's length into r0 and calculate new length. 15288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 15298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang STATIC_ASSERT(kSmiTagSize == 1); 15308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang STATIC_ASSERT(kSmiTag == 0); 15318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ add(r0, r0, Operand(Smi::FromInt(argc))); 15328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 15333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the elements' length. 15348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset)); 15358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 15368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check if we could survive without allocation. 15378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ cmp(r0, r4); 15388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(gt, &attempt_to_grow_elements); 15398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 15403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if value is a smi. 15413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label with_write_barrier; 15423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r4, MemOperand(sp, (argc - 1) * kPointerSize)); 15433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfNotSmi(r4, &with_write_barrier); 15443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Save new length. 15468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 15478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 15483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the value. 15498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // We may need a register containing the address end_elements below, 15508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // so write back the value in end_elements. 15518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ add(end_elements, elements, 15528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); 15538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const int kEndElementsOffset = 15548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize; 15558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex)); 15568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 15578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check for a smi. 15588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(argc + 1); 15598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 15608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 15618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&with_write_barrier); 15623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r3, FieldMemOperand(receiver, HeapObject::kMapOffset)); 15643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) { 15663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label fast_object, not_fast_object; 15673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastObjectElements(r3, r7, ¬_fast_object); 15683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&fast_object); 15693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // In case of fast smi-only, convert to fast object, otherwise bail out. 15703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(¬_fast_object); 15713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastSmiOnlyElements(r3, r7, &call_builtin); 15723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // edx: receiver 15733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r3: map 15743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS, 15753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FAST_ELEMENTS, 15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r3, 15773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r7, 15783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &call_builtin); 15793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r2, receiver); 15803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsTransitionGenerator::GenerateSmiOnlyToObject(masm()); 15813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&fast_object); 15823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 15833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastObjectElements(r3, r3, &call_builtin); 15843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 15853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Save new length. 15873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 15883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the value. 15903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We may need a register containing the address end_elements below, 15913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // so write back the value in end_elements. 15923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(end_elements, elements, 15933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); 15943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex)); 15953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWrite(elements, 15973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch end_elements, 15983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r4, 15993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kLRHasNotBeenSaved, 16003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, 16013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, 16023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_SMI_CHECK); 16038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(argc + 1); 16048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 16058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 16068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&attempt_to_grow_elements); 16078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // r0: array's length + 1. 16088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // r4: elements' length. 16098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 16108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang if (!FLAG_inline_new) { 16118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&call_builtin); 16128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 16138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 16143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r2, MemOperand(sp, (argc - 1) * kPointerSize)); 16153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Growing elements that are SMI-only requires special handling in case 16163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the new element is non-Smi. For now, delegate to the builtin. 16173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label no_fast_elements_check; 16183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(r2, &no_fast_elements_check); 16193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r7, FieldMemOperand(receiver, HeapObject::kMapOffset)); 16203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastObjectElements(r7, r7, &call_builtin); 16213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&no_fast_elements_check); 16223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 162344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate = masm()->isolate(); 16248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ExternalReference new_space_allocation_top = 162544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::new_space_allocation_top_address(isolate); 16268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ExternalReference new_space_allocation_limit = 162744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::new_space_allocation_limit_address(isolate); 16288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 16298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const int kAllocationDelta = 4; 16308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load top and check if it is the end of elements. 16318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ add(end_elements, elements, 16328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); 16338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ add(end_elements, end_elements, Operand(kEndElementsOffset)); 16348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(r7, Operand(new_space_allocation_top)); 16353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r3, MemOperand(r7)); 16363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(end_elements, r3); 16378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(ne, &call_builtin); 16388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 16398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(r9, Operand(new_space_allocation_limit)); 16408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r9, MemOperand(r9)); 16413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(r3, r3, Operand(kAllocationDelta * kPointerSize)); 16423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r3, r9); 16438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(hi, &call_builtin); 16448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 16458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // We fit and could grow elements. 16468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Update new_space_allocation_top. 16473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r3, MemOperand(r7)); 16488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Push the argument. 16493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r2, MemOperand(end_elements)); 16508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Fill the rest with holes. 16513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r3, Heap::kTheHoleValueRootIndex); 16528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang for (int i = 1; i < kAllocationDelta; i++) { 16533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r3, MemOperand(end_elements, i * kPointerSize)); 16548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 16558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 16568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Update elements' and array's sizes. 16578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 16588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ add(r4, r4, Operand(Smi::FromInt(kAllocationDelta))); 16598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(r4, FieldMemOperand(elements, FixedArray::kLengthOffset)); 16608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 16618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Elements are in new space, so write barrier is not required. 16628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(argc + 1); 16638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 16648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 16658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&call_builtin); 166644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush, 166744f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm()->isolate()), 16688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang argc + 1, 16698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1); 16708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 16716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Handle call cache miss. 16736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss); 16743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 16756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return the generated code. 167725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen return GetCode(function); 16786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 16796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16813ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPopCall( 16823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 16833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 16843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 16853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 16863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1688402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- r2 : name 1689402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- lr : return address 16908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 16918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- ... 16928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- sp[argc * 4] : receiver 1693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 16946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 169559151504615d929945dc59db37bf1166937748c6Steve Block // If object is not an array, bail out to regular call. 16963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); 16976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 16988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label miss, return_undefined, call_builtin; 16998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register receiver = r1; 17008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register elements = r3; 17019dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateNameCheck(name, &miss); 17029dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 1703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the receiver from the stack 1704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 17058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); 1706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 17071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(receiver, &miss); 17086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the maps haven't changed. 17103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, elements, 17113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r4, r0, name, &miss); 17128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 17138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Get the elements array of the object. 17148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); 17156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check that the elements are in fast mode and writable. 1717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CheckMap(elements, 1718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch r0, 1719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Heap::kFixedArrayMapRootIndex, 1720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &call_builtin, 1721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DONT_DO_SMI_CHECK); 17228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 17238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Get the array's length into r4 and calculate new length. 17248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r4, FieldMemOperand(receiver, JSArray::kLengthOffset)); 17258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ sub(r4, r4, Operand(Smi::FromInt(1)), SetCC); 17268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(lt, &return_undefined); 17278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 17288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Get the last element. 17298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ LoadRoot(r6, Heap::kTheHoleValueRootIndex); 17308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang STATIC_ASSERT(kSmiTagSize == 1); 17318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang STATIC_ASSERT(kSmiTag == 0); 17328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // We can't address the last element in one operation. Compute the more 17338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // expensive shift first, and use an offset later on. 17348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ add(elements, elements, Operand(r4, LSL, kPointerSizeLog2 - kSmiTagSize)); 17358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r0, MemOperand(elements, FixedArray::kHeaderSize - kHeapObjectTag)); 17368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ cmp(r0, r6); 17378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(eq, &call_builtin); 17388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 17398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Set the array's length. 17408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(r4, FieldMemOperand(receiver, JSArray::kLengthOffset)); 17418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 17428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Fill with the hole. 17438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(r6, MemOperand(elements, FixedArray::kHeaderSize - kHeapObjectTag)); 17448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(argc + 1); 17458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 17468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 17478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&return_undefined); 17488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 17498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(argc + 1); 17508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 17518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 17528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&call_builtin); 175344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop, 175444f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm()->isolate()), 17556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block argc + 1, 17566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1); 17576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Handle call cache miss. 17596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss); 17603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 17616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return the generated code. 176325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen return GetCode(function); 17646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 17656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 17673ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharCodeAtCall( 17683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 17693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 17703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 17713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 17723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 177380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ----------- S t a t e ------------- 177480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- r2 : function name 177580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- lr : return address 177680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 177780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- ... 177880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- sp[argc * 4] : receiver 177980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ----------------------------------- 178080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 178180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // If object is not a string, bail out to regular call. 17823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); 178380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 178480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen const int argc = arguments().immediate(); 178580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label miss; 1786b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label name_miss; 178780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label index_out_of_range; 1788b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label* index_out_of_range_label = &index_out_of_range; 1789b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (kind_ == Code::CALL_IC && 17913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (CallICBase::StringStubState::decode(extra_state_) == 1792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DEFAULT_STRING_STUB)) { 1793b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch index_out_of_range_label = &miss; 1794b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1795b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch GenerateNameCheck(name, &name_miss); 179680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 179780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check that the maps starting from the prototype haven't changed. 179880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen GenerateDirectLoadGlobalFunctionPrototype(masm(), 179980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Context::STRING_FUNCTION_INDEX, 18000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen r0, 18010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &miss); 18023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!object.is_identical_to(holder)); 18033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())), 18043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r0, holder, r1, r3, r4, name, &miss); 180580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 180680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Register receiver = r1; 180780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Register index = r4; 180880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Register result = r0; 180980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); 181080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (argc > 0) { 181180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize)); 181280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 181380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadRoot(index, Heap::kUndefinedValueRootIndex); 181480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 181580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 18163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringCharCodeAtGenerator generator(receiver, 18173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index, 18183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result, 18193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a string. 18203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a number. 18213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index_out_of_range_label, 18223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STRING_INDEX_IS_NUMBER); 18233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateFast(masm()); 182480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Drop(argc + 1); 182580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Ret(); 182680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch StubRuntimeCallHelper call_helper; 18283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateSlow(masm(), call_helper); 182980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1830b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (index_out_of_range.is_linked()) { 1831b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&index_out_of_range); 1832b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ LoadRoot(r0, Heap::kNanValueRootIndex); 1833b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ Drop(argc + 1); 1834b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ Ret(); 1835b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 183680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 183780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&miss); 1838b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Restore function name in r2. 18393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(r2, name); 1840b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&name_miss); 18413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 184280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 184380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Return the generated code. 184480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen return GetCode(function); 18457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 18467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 18477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 18483ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharAtCall( 18493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 18503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 18513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 18523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 18533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 185480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ----------- S t a t e ------------- 185580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- r2 : function name 185680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- lr : return address 185780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 185880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- ... 185980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- sp[argc * 4] : receiver 186080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ----------------------------------- 186180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 186280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // If object is not a string, bail out to regular call. 18633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); 186480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 186580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen const int argc = arguments().immediate(); 186680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label miss; 1867b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label name_miss; 186880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label index_out_of_range; 1869b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label* index_out_of_range_label = &index_out_of_range; 1870257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (kind_ == Code::CALL_IC && 18713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (CallICBase::StringStubState::decode(extra_state_) == 1872257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DEFAULT_STRING_STUB)) { 1873b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch index_out_of_range_label = &miss; 1874b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1875b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch GenerateNameCheck(name, &name_miss); 187680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 187780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check that the maps starting from the prototype haven't changed. 187880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen GenerateDirectLoadGlobalFunctionPrototype(masm(), 187980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Context::STRING_FUNCTION_INDEX, 18800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen r0, 18810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &miss); 18823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!object.is_identical_to(holder)); 18833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())), 18843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r0, holder, r1, r3, r4, name, &miss); 188580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 188680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Register receiver = r0; 188780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Register index = r4; 18883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch = r3; 188980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Register result = r0; 189080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); 189180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (argc > 0) { 189280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize)); 189380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 189480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadRoot(index, Heap::kUndefinedValueRootIndex); 189580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 189680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 18973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringCharAtGenerator generator(receiver, 18983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index, 18993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 19003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result, 19013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a string. 19023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a number. 19033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index_out_of_range_label, 19043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STRING_INDEX_IS_NUMBER); 19053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateFast(masm()); 190680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Drop(argc + 1); 190780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Ret(); 190880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch StubRuntimeCallHelper call_helper; 19103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateSlow(masm(), call_helper); 191180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1912b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (index_out_of_range.is_linked()) { 1913b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&index_out_of_range); 1914b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ LoadRoot(r0, Heap::kEmptyStringRootIndex); 1915b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ Drop(argc + 1); 1916b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ Ret(); 1917b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 191880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 191980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&miss); 1920b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Restore function name in r2. 19213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(r2, name); 1922b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&name_miss); 19233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 192480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 192580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Return the generated code. 192680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen return GetCode(function); 19277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 19287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 19297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 19303ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringFromCharCodeCall( 19313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 19323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 19333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 19343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 19353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 193659151504615d929945dc59db37bf1166937748c6Steve Block // ----------- S t a t e ------------- 193759151504615d929945dc59db37bf1166937748c6Steve Block // -- r2 : function name 193859151504615d929945dc59db37bf1166937748c6Steve Block // -- lr : return address 193959151504615d929945dc59db37bf1166937748c6Steve Block // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 194059151504615d929945dc59db37bf1166937748c6Steve Block // -- ... 194159151504615d929945dc59db37bf1166937748c6Steve Block // -- sp[argc * 4] : receiver 194259151504615d929945dc59db37bf1166937748c6Steve Block // ----------------------------------- 194359151504615d929945dc59db37bf1166937748c6Steve Block 194459151504615d929945dc59db37bf1166937748c6Steve Block const int argc = arguments().immediate(); 194559151504615d929945dc59db37bf1166937748c6Steve Block 194659151504615d929945dc59db37bf1166937748c6Steve Block // If the object is not a JSObject or we got an unexpected number of 194759151504615d929945dc59db37bf1166937748c6Steve Block // arguments, bail out to the regular call. 19483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); 194959151504615d929945dc59db37bf1166937748c6Steve Block 195059151504615d929945dc59db37bf1166937748c6Steve Block Label miss; 195159151504615d929945dc59db37bf1166937748c6Steve Block GenerateNameCheck(name, &miss); 195259151504615d929945dc59db37bf1166937748c6Steve Block 19533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (cell.is_null()) { 195459151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); 195559151504615d929945dc59db37bf1166937748c6Steve Block 195659151504615d929945dc59db37bf1166937748c6Steve Block STATIC_ASSERT(kSmiTag == 0); 19573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(r1, &miss); 195859151504615d929945dc59db37bf1166937748c6Steve Block 19593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4, 19603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 196159151504615d929945dc59db37bf1166937748c6Steve Block } else { 19623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(cell->value() == *function); 19633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 19643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 196559151504615d929945dc59db37bf1166937748c6Steve Block GenerateLoadFunctionFromCell(cell, function, &miss); 196659151504615d929945dc59db37bf1166937748c6Steve Block } 196759151504615d929945dc59db37bf1166937748c6Steve Block 196859151504615d929945dc59db37bf1166937748c6Steve Block // Load the char code argument. 196959151504615d929945dc59db37bf1166937748c6Steve Block Register code = r1; 197059151504615d929945dc59db37bf1166937748c6Steve Block __ ldr(code, MemOperand(sp, 0 * kPointerSize)); 197159151504615d929945dc59db37bf1166937748c6Steve Block 197259151504615d929945dc59db37bf1166937748c6Steve Block // Check the code is a smi. 197359151504615d929945dc59db37bf1166937748c6Steve Block Label slow; 197459151504615d929945dc59db37bf1166937748c6Steve Block STATIC_ASSERT(kSmiTag == 0); 19753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(code, &slow); 197659151504615d929945dc59db37bf1166937748c6Steve Block 197759151504615d929945dc59db37bf1166937748c6Steve Block // Convert the smi code to uint16. 197859151504615d929945dc59db37bf1166937748c6Steve Block __ and_(code, code, Operand(Smi::FromInt(0xffff))); 197959151504615d929945dc59db37bf1166937748c6Steve Block 19803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringCharFromCodeGenerator generator(code, r0); 19813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateFast(masm()); 198259151504615d929945dc59db37bf1166937748c6Steve Block __ Drop(argc + 1); 198359151504615d929945dc59db37bf1166937748c6Steve Block __ Ret(); 198459151504615d929945dc59db37bf1166937748c6Steve Block 1985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch StubRuntimeCallHelper call_helper; 19863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateSlow(masm(), call_helper); 198759151504615d929945dc59db37bf1166937748c6Steve Block 198859151504615d929945dc59db37bf1166937748c6Steve Block // Tail call the full function. We do not have to patch the receiver 198959151504615d929945dc59db37bf1166937748c6Steve Block // because the function makes no use of it. 199059151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&slow); 19913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeFunction( 19923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); 199359151504615d929945dc59db37bf1166937748c6Steve Block 199459151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&miss); 199559151504615d929945dc59db37bf1166937748c6Steve Block // r2: function name. 19963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 199759151504615d929945dc59db37bf1166937748c6Steve Block 199859151504615d929945dc59db37bf1166937748c6Steve Block // Return the generated code. 19993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); 200059151504615d929945dc59db37bf1166937748c6Steve Block} 200159151504615d929945dc59db37bf1166937748c6Steve Block 200259151504615d929945dc59db37bf1166937748c6Steve Block 20033ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathFloorCall( 20043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 20053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 20063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 20073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 20083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 20098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // ----------- S t a t e ------------- 20108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- r2 : function name 20118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- lr : return address 20128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 20138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- ... 20148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- sp[argc * 4] : receiver 20158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // ----------------------------------- 20168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (!CpuFeatures::IsSupported(VFP3)) { 20183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Handle<Code>::null(); 201944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 202044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 20218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CpuFeatures::Scope scope_vfp3(VFP3); 20228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const int argc = arguments().immediate(); 20238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // If the object is not a JSObject or we got an unexpected number of 20248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // arguments, bail out to the regular call. 20253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); 20268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label miss, slow; 20288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GenerateNameCheck(name, &miss); 20298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (cell.is_null()) { 20318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); 20328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang STATIC_ASSERT(kSmiTag == 0); 20331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r1, &miss); 20343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4, 20353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 20368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } else { 20373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(cell->value() == *function); 20383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 20393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 20408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GenerateLoadFunctionFromCell(cell, function, &miss); 20418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 20428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load the (only) argument into r0. 20448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); 20458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // If the argument is a smi, just return. 20478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang STATIC_ASSERT(kSmiTag == 0); 20488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ tst(r0, Operand(kSmiTagMask)); 20498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(argc + 1, eq); 20508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(eq); 20518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 2052257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK); 20538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label wont_fit_smi, no_vfp_exception, restore_fpscr_and_return; 20558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // If vfp3 is enabled, we use the fpu rounding with the RM (round towards 20578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // minus infinity) mode. 20588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load the HeapNumber value. 20608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // We will need access to the value in the core registers, so we load it 20618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // with ldrd and move it to the fpu. It also spares a sub instruction for 20628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // updating the HeapNumber value address, as vldr expects a multiple 20638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // of 4 offset. 20648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ldrd(r4, r5, FieldMemOperand(r0, HeapNumber::kValueOffset)); 20658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ vmov(d1, r4, r5); 20668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Backup FPSCR. 20688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ vmrs(r3); 20698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Set custom FPCSR: 20708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // - Set rounding mode to "Round towards Minus Infinity" 20713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // (i.e. bits [23:22] = 0b10). 20728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // - Clear vfp cumulative exception flags (bits [3:0]). 20738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // - Make sure Flush-to-zero mode control bit is unset (bit 22). 20748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bic(r9, r3, 20758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Operand(kVFPExceptionMask | kVFPRoundingModeMask | kVFPFlushToZeroMask)); 20761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ orr(r9, r9, Operand(kRoundToMinusInf)); 20778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ vmsr(r9); 20788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Convert the argument to an integer. 20801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ vcvt_s32_f64(s0, d1, kFPSCRRounding); 20818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Use vcvt latency to start checking for special cases. 20838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Get the argument exponent and clear the sign bit. 20848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bic(r6, r5, Operand(HeapNumber::kSignMask)); 20858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(r6, Operand(r6, LSR, HeapNumber::kMantissaBitsInTopWord)); 20868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Retrieve FPSCR and check for vfp exceptions. 20888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ vmrs(r9); 20898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ tst(r9, Operand(kVFPExceptionMask)); 20908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&no_vfp_exception, eq); 20918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check for NaN, Infinity, and -Infinity. 20938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // They are invariant through a Math.Floor call, so just 20948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // return the original argument. 20958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ sub(r7, r6, Operand(HeapNumber::kExponentMask 20968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang >> HeapNumber::kMantissaBitsInTopWord), SetCC); 20978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&restore_fpscr_and_return, eq); 20988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // We had an overflow or underflow in the conversion. Check if we 20998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // have a big exponent. 21008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ cmp(r7, Operand(HeapNumber::kMantissaBits)); 21018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // If greater or equal, the argument is already round and in r0. 21028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&restore_fpscr_and_return, ge); 2103b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ b(&wont_fit_smi); 21048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 21058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&no_vfp_exception); 21068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Move the result back to general purpose register r0. 21078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ vmov(r0, s0); 21088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check if the result fits into a smi. 21098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ add(r1, r0, Operand(0x40000000), SetCC); 21108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&wont_fit_smi, mi); 21118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Tag the result. 21128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang STATIC_ASSERT(kSmiTag == 0); 21138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(r0, Operand(r0, LSL, kSmiTagSize)); 21148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 21158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check for -0. 2116b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ cmp(r0, Operand(0, RelocInfo::NONE)); 21178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&restore_fpscr_and_return, ne); 21188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // r5 already holds the HeapNumber exponent. 21198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ tst(r5, Operand(HeapNumber::kSignMask)); 21208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // If our HeapNumber is negative it was -0, so load its address and return. 21218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Else r0 is loaded with 0, so we can also just return. 21228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r0, MemOperand(sp, 0 * kPointerSize), ne); 21238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 21248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&restore_fpscr_and_return); 21258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Restore FPSCR and return. 21268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ vmsr(r3); 21278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(argc + 1); 21288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 21298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 21308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&wont_fit_smi); 21318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Restore FPCSR and fall to slow case. 21328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ vmsr(r3); 21338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 2134b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&slow); 21358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Tail call the full function. We do not have to patch the receiver 21368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // because the function makes no use of it. 21373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeFunction( 21383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); 21398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 21408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&miss); 21418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // r2: function name. 21423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 21438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 21448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Return the generated code. 21453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); 21460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 21470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 21480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 21493ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathAbsCall( 21503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 21513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 21523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 21533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 21543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2155f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // ----------- S t a t e ------------- 2156f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- r2 : function name 2157f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- lr : return address 2158f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 2159f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- ... 2160f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- sp[argc * 4] : receiver 2161f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // ----------------------------------- 2162f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2163f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch const int argc = arguments().immediate(); 2164f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // If the object is not a JSObject or we got an unexpected number of 2165f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // arguments, bail out to the regular call. 21663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); 2167f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2168f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Label miss; 2169f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch GenerateNameCheck(name, &miss); 21703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (cell.is_null()) { 2171f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); 2172f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch STATIC_ASSERT(kSmiTag == 0); 21733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(r1, &miss); 21743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4, 21753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 2176f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch } else { 21773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(cell->value() == *function); 21783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 21793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 2180f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch GenerateLoadFunctionFromCell(cell, function, &miss); 2181f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch } 2182f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2183f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Load the (only) argument into r0. 2184f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); 2185f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2186f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Check if the argument is a smi. 2187f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Label not_smi; 2188f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch STATIC_ASSERT(kSmiTag == 0); 21891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfNotSmi(r0, ¬_smi); 2190f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2191f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Do bitwise not or do nothing depending on the sign of the 2192f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // argument. 2193f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ eor(r1, r0, Operand(r0, ASR, kBitsPerInt - 1)); 2194f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2195f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Add 1 or do nothing depending on the sign of the argument. 2196f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ sub(r0, r1, Operand(r0, ASR, kBitsPerInt - 1), SetCC); 2197f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2198f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // If the result is still negative, go to the slow case. 2199f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // This only happens for the most negative smi. 2200f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Label slow; 2201f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ b(mi, &slow); 2202f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2203f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Smi case done. 2204f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ Drop(argc + 1); 2205f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ Ret(); 2206f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2207f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Check if the argument is a heap number and load its exponent and 2208f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // sign. 2209f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(¬_smi); 2210257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK); 2211f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ ldr(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset)); 2212f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2213f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Check the sign of the argument. If the argument is positive, 2214f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // just return it. 2215f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Label negative_sign; 2216f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ tst(r1, Operand(HeapNumber::kSignMask)); 2217f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ b(ne, &negative_sign); 2218f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ Drop(argc + 1); 2219f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ Ret(); 2220f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2221f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // If the argument is negative, clear the sign, and return a new 2222f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // number. 2223f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(&negative_sign); 2224f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ eor(r1, r1, Operand(HeapNumber::kSignMask)); 2225f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); 2226f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); 2227f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ AllocateHeapNumber(r0, r4, r5, r6, &slow); 2228f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ str(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset)); 2229f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ str(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); 2230f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ Drop(argc + 1); 2231f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ Ret(); 2232f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2233f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Tail call the full function. We do not have to patch the receiver 2234f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // because the function makes no use of it. 2235f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(&slow); 22363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeFunction( 22373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); 2238f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2239f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(&miss); 2240f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // r2: function name. 22413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2242f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2243f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Return the generated code. 22443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); 2245f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch} 2246f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 2247f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 22483ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileFastApiCall( 224944f0eee88ff00398ff7f715fab053374d808c90dSteve Block const CallOptimization& optimization, 22503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 22513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 22523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 22533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 22543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 225544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 225644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 225744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(optimization.is_simple_api_call()); 225844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Bail out if object is a global object as we don't want to 225944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // repatch it to global receiver. 22603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (object->IsGlobalObject()) return Handle<Code>::null(); 22613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!cell.is_null()) return Handle<Code>::null(); 22623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSObject()) return Handle<Code>::null(); 226344f0eee88ff00398ff7f715fab053374d808c90dSteve Block int depth = optimization.GetPrototypeDepthOfExpectedType( 22643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>::cast(object), holder); 22653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (depth == kInvalidProtoDepth) return Handle<Code>::null(); 226644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 226744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label miss, miss_before_stack_reserved; 226844f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenerateNameCheck(name, &miss_before_stack_reserved); 226944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 227044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Get the receiver from the stack. 227144f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int argc = arguments().immediate(); 227244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ ldr(r1, MemOperand(sp, argc * kPointerSize)); 227344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 227444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the receiver isn't a smi. 22753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(r1, &miss_before_stack_reserved); 227644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 227744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_const(), 1, r0, r3); 227844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_const_fast_api(), 1, r0, r3); 227944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 228044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ReserveSpaceForFastApiCall(masm(), r0); 228144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 228244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the maps haven't changed and find a Holder as a side effect. 22833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4, name, 228444f0eee88ff00398ff7f715fab053374d808c90dSteve Block depth, &miss); 228544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 22863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateFastApiDirectCall(masm(), optimization, argc); 228744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 228844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&miss); 228944f0eee88ff00398ff7f715fab053374d808c90dSteve Block FreeSpaceForFastApiCall(masm()); 229044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 229144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&miss_before_stack_reserved); 22923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 229344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 229444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Return the generated code. 229544f0eee88ff00398ff7f715fab053374d808c90dSteve Block return GetCode(function); 229644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 229744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 229844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 22993ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object, 23003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 23013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 23023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 23035913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck CheckType check) { 23046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 23056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- r2 : name 23066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- lr : return address 23076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 230844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (HasCustomCallGenerator(function)) { 23093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = CompileCustomCall(object, holder, 23103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell>::null(), 23113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function, name); 23123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // A null handle means bail out to the regular compiler code below. 23133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!code.is_null()) return code; 23146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 23156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 231644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label miss; 231744f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenerateNameCheck(name, &miss); 23189dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 23196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the receiver from the stack 23206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int argc = arguments().immediate(); 23216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ldr(r1, MemOperand(sp, argc * kPointerSize)); 23226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 23236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the receiver isn't a smi. 2324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check != NUMBER_CHECK) { 23253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(r1, &miss); 2326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure that it's okay not to patch the on stack receiver 2329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // unless we're doing a receiver map check. 2330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); 2331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (check) { 2332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case RECEIVER_MAP_CHECK: 233344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(masm()->isolate()->counters()->call_const(), 233444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1, r0, r3); 23356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the maps haven't changed. 23373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4, 23383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 2339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack with the global proxy if 2341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // necessary. 2342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsGlobalObject()) { 2343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); 2344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r3, MemOperand(sp, argc * kPointerSize)); 2345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 2347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case STRING_CHECK: 23493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (function->IsBuiltin() || !function->shared()->is_classic_mode()) { 2350e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the object is a two-byte string or a symbol. 2351402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE); 23523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ b(ge, &miss); 2353e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the maps starting from the prototype haven't changed. 23547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype( 23550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen masm(), Context::STRING_FUNCTION_INDEX, r0, &miss); 23563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes( 23573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(JSObject::cast(object->GetPrototype())), 23583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r0, holder, r3, r1, r4, name, &miss); 23593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 236085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // Calling non-strict non-builtins with a value as the receiver 236185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // requires boxing. 236285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch __ jmp(&miss); 23633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 23643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 23653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 23663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case NUMBER_CHECK: 23673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (function->IsBuiltin() || !function->shared()->is_classic_mode()) { 2368e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label fast; 2369e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the object is a smi or a heap number. 23703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(r1, &fast); 2371402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE); 2372e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ b(ne, &miss); 2373e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&fast); 2374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the maps starting from the prototype haven't changed. 23757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype( 23760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss); 23773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes( 23783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(JSObject::cast(object->GetPrototype())), 23793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r0, holder, r3, r1, r4, name, &miss); 23803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 238185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // Calling non-strict non-builtins with a value as the receiver 238285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // requires boxing. 238385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch __ jmp(&miss); 23843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 23853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 23863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 23873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case BOOLEAN_CHECK: 23883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (function->IsBuiltin() || !function->shared()->is_classic_mode()) { 2389e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label fast; 2390e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the object is a boolean. 2391e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadRoot(ip, Heap::kTrueValueRootIndex); 2392e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(r1, ip); 2393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ b(eq, &fast); 2394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ LoadRoot(ip, Heap::kFalseValueRootIndex); 2395e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(r1, ip); 2396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ b(ne, &miss); 2397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&fast); 2398e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check that the maps starting from the prototype haven't changed. 23997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch GenerateDirectLoadGlobalFunctionPrototype( 24000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen masm(), Context::BOOLEAN_FUNCTION_INDEX, r0, &miss); 24013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes( 24023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(JSObject::cast(object->GetPrototype())), 24033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r0, holder, r3, r1, r4, name, &miss); 24043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 24053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Calling non-strict non-builtins with a value as the receiver 24063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // requires boxing. 24073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&miss); 2408e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 2410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 2414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 24153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeFunction( 24163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function, arguments(), JUMP_FUNCTION, NullCallWrapper(), call_kind); 2417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 2419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 24203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 242325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen return GetCode(function); 2424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24273ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, 24283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 24293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2431402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- r2 : name 2432402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- lr : return address 2433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 24346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss; 24359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateNameCheck(name, &miss); 24369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 24374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Get the number of arguments. 24384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke const int argc = arguments().immediate(); 24393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 24404515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke LookupPostInterceptor(holder, name, &lookup); 24414515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 24426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the receiver from the stack. 24436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ldr(r1, MemOperand(sp, argc * kPointerSize)); 2444402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 24453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallInterceptorCompiler compiler(this, arguments(), r2, extra_state_); 24463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch compiler.Compile(masm(), object, holder, name, &lookup, r1, r3, r4, r0, 24473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 2448402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 2449402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Move returned value, the function to call, to r1. 2450402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(r1, r0); 24514515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Restore receiver. 24526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ldr(r0, MemOperand(sp, argc * kPointerSize)); 24534515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 24543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); 2455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 2457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 24583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24653ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallGlobal( 24663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 24673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject> holder, 24683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 24693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 24703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2472402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- r2 : name 2473402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- lr : return address 2474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 247544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (HasCustomCallGenerator(function)) { 24763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = CompileCustomCall(object, holder, cell, function, name); 24773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // A null handle means bail out to the regular compiler code below. 24783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!code.is_null()) return code; 247959151504615d929945dc59db37bf1166937748c6Steve Block } 248059151504615d929945dc59db37bf1166937748c6Steve Block 2481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 24829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GenerateNameCheck(name, &miss); 24839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 2484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the number of arguments. 2485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 248659151504615d929945dc59db37bf1166937748c6Steve Block GenerateGlobalReceiverCheck(object, holder, name, &miss); 248759151504615d929945dc59db37bf1166937748c6Steve Block GenerateLoadFunctionFromCell(cell, function, &miss); 2488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the receiver on the stack with the global proxy if 2490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // necessary. 2491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsGlobalObject()) { 2492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); 2493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r3, MemOperand(sp, argc * kPointerSize)); 2494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the context (function already in r1). 2497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 2498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the cached code (tail call). 250044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = masm()->isolate()->counters(); 250144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_global_inline(), 1, r3, r4); 2502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount expected(function->shared()->formal_parameter_count()); 25033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 2505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 25063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We call indirectly through the code field in the function to 25073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // allow recompilation to take effect without changing any of the 25083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // call sites. 25093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); 25103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeCode(r3, expected, arguments(), JUMP_FUNCTION, 25113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch NullCallWrapper(), call_kind); 2512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle call cache miss. 2514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 251544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_global_inline_miss(), 1, r1, r3); 25163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(NORMAL, name); 2520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25233ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, 25245913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index, 25253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> transition, 25263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : value 2529402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- r1 : receiver 2530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 2531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateStoreField(masm(), object, index, transition, r1, r2, r3, &miss); 2536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 253744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); 2538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 2539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 25413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); 2542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25453ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreCallback( 25463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 25473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback, 25483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : value 2551402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- r1 : receiver 2552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 2553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the object hasn't changed. 25583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(r1, r3, Handle<Map>(object->map()), &miss, 25593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); 2560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform global security token check if needed. 2562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsJSGlobalProxy()) { 2563402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CheckAccessGlobalProxy(r1, r3, &miss); 2564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stub never generated for non-global objects that require access 2567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks. 2568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 2569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2570402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(r1); // receiver 25713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ip, Operand(callback)); // callback info 25726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Push(ip, r2, r0); 2573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to the runtime system. 2575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference store_callback_property = 257644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kStoreCallbackProperty), 257744f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm()->isolate()); 25786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ TailCallExternalReference(store_callback_property, 4, 1); 2579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 258244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); 2583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 2584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25903ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreInterceptor( 25913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 25923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : value 2595402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- r1 : receiver 2596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 2597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the object hasn't changed. 26023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(r1, r3, Handle<Map>(receiver->map()), &miss, 26033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); 2604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform global security token check if needed. 2606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (receiver->IsJSGlobalProxy()) { 2607402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CheckAccessGlobalProxy(r1, r3, &miss); 2608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2610402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Stub is never generated for non-global objects that require access 2611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks. 2612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); 2613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 26146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Push(r1, r2, r0); // Receiver, name, value. 2615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2616e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(r0, Operand(Smi::FromInt(strict_mode_))); 2617e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(r0); // strict mode 2618e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to the runtime system. 2620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference store_ic_property = 262144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), 262244f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm()->isolate()); 2623e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ TailCallExternalReference(store_ic_property, 4, 1); 2624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 262744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); 2628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 2629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 26353ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreGlobal( 26363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject> object, 26373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 26383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : value 2641402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // -- r1 : receiver 2642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 2643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the global has not changed. 2648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); 2649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r3, Operand(Handle<Map>(object->map()))); 2650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 2651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 26521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the value in the cell is not the hole. If it is, this 26531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // cell could have been deleted and reintroducing the global needs 26541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // to update the property details in the property dictionary of the 26551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // global object. We bail out to the runtime system to do that. 26563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r4, Operand(cell)); 26571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ LoadRoot(r5, Heap::kTheHoleValueRootIndex); 26581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldr(r6, FieldMemOperand(r4, JSGlobalPropertyCell::kValueOffset)); 26591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmp(r5, r6); 26601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(eq, &miss); 26611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Store the value in the cell. 26631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ str(r0, FieldMemOperand(r4, JSGlobalPropertyCell::kValueOffset)); 26643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Cells are always rescanned, so no write barrier here. 2665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 266644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = masm()->isolate()->counters(); 266744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_store_global_inline(), 1, r4, r3); 2668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Ret(); 2669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 267244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_store_global_inline_miss(), 1, r4, r3); 267344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); 2674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 2675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(NORMAL, name); 2678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 26813ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name, 26823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 26833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> last) { 26846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 2685f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -- r0 : receiver 26866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- lr : return address 26876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 26886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss; 26896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 26906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that receiver is not a smi. 26913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(r0, &miss); 26926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 26936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check the maps of the full prototype chain. 26943bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CheckPrototypes(object, r0, last, r3, r1, r4, name, &miss); 26956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 26966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // If the last object in the prototype chain is a global object, 26976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // check that the global property cell is empty. 26986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (last->IsGlobalObject()) { 26993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateCheckPropertyCell( 27003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm(), Handle<GlobalObject>::cast(last), name, r1, &miss); 27016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 27026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 27036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return undefined if maps of the full prototype chain are still the 27046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // same and no global property with this name contains a value. 27056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 27066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Ret(); 27076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 27086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss); 27096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 27106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 27116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return the generated code. 27123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NONEXISTENT, factory()->empty_string()); 27136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 27146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 27156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 27163ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object, 27173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 27185913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index, 27193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2721f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -- r0 : receiver 2722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 2723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch GenerateLoadField(object, holder, r0, r3, r1, r4, index, name, &miss); 2728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(FIELD, name); 2733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27363ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadCallback( 27373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 27383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 27393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 27403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback) { 2741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2742f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -- r0 : receiver 2743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 2744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 27473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadCallback(object, holder, r0, r2, r3, r1, r4, callback, name, 27483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 2749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27573ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object, 27583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 27593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> value, 27603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -- r0 : receiver 2763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 2764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27683bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch GenerateLoadConstant(object, holder, r0, r3, r1, r4, value, name, &miss); 2769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CONSTANT_FUNCTION, name); 2774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27773ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> object, 27783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 27793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2781f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -- r0 : receiver 2782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 2783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 27884515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke LookupPostInterceptor(holder, name, &lookup); 27893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadInterceptor(object, holder, &lookup, r0, r2, r3, r1, r4, name, 2790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &miss); 2791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27993ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadGlobal( 28003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 28013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject> holder, 28023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 28033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 28043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_dont_delete) { 2805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -- r0 : receiver 2807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : name 2808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 2809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the global has not changed. 28133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(r0, &miss); 28143bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CheckPrototypes(object, r0, holder, r3, r4, r1, name, &miss); 2815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the value from the cell. 28173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r3, Operand(cell)); 28186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ldr(r4, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); 2819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for deleted property if property can actually be deleted. 2821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!is_dont_delete) { 2822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 28236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(r4, ip); 2824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &miss); 2825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(r0, r4); 282844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = masm()->isolate()->counters(); 282944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3); 2830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Ret(); 2831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 283344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_load_global_stub_miss(), 1, r1, r3); 2834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 2835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(NORMAL, name); 2838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28413ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name, 28423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 28433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 28445913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index) { 2845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 28476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- r0 : key 284825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // -- r1 : receiver 2849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check the key is the cached one. 28533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r0, Operand(name)); 2854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 2855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28563bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch GenerateLoadField(receiver, holder, r1, r2, r3, r4, index, name, &miss); 2857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(FIELD, name); 2861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28643ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadCallback( 28653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 28663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 28673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 28683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback) { 2869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 28716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- r0 : key 287225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // -- r1 : receiver 2873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check the key is the cached one. 28773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r0, Operand(name)); 2878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 2879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadCallback(receiver, holder, r1, r0, r2, r3, r4, callback, name, 28813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 2882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28893ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadConstant( 28903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 28913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 28923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 28933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> value) { 2894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 28966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- r0 : key 289725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // -- r1 : receiver 2898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check the key is the cached one. 29023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r0, Operand(name)); 2903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 2904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29053bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch GenerateLoadConstant(receiver, holder, r1, r2, r3, r4, value, name, &miss); 2906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CONSTANT_FUNCTION, name); 2911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29143ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor( 29153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 29163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 29173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 29206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- r0 : key 292125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // -- r1 : receiver 2922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check the key is the cached one. 29263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r0, Operand(name)); 2927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 2928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 29304515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke LookupPostInterceptor(holder, name, &lookup); 29313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadInterceptor(receiver, holder, &lookup, r1, r0, r2, r3, r4, name, 2932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &miss); 2933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29403ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength( 29413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 29446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- r0 : key 294525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // -- r1 : receiver 2946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check the key is the cached one. 29503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r0, Operand(name)); 2951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 2952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block GenerateLoadArrayLength(masm(), r1, r2, &miss); 2954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29613ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadStringLength( 29623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 29656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- r0 : key 296625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // -- r1 : receiver 2967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 296944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 297044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = masm()->isolate()->counters(); 297144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_string_length(), 1, r2, r3); 2972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check the key is the cached one. 29743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r0, Operand(name)); 2975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 2976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block GenerateLoadStringLength(masm(), r1, r2, r3, &miss, true); 2978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 297944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_string_length(), 1, r2, r3); 2980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 2984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29873ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype( 29883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 29916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- r0 : key 299225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // -- r1 : receiver 2993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 29948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label miss; 29958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 299644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = masm()->isolate()->counters(); 299744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_function_prototype(), 1, r2, r3); 29988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 29998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Check the name hasn't changed. 30003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r0, Operand(name)); 30018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(ne, &miss); 30028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 30038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GenerateLoadFunctionPrototype(masm(), r1, r2, r3, &miss); 30048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&miss); 300544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_function_prototype(), 1, r2, r3); 3006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(CALLBACKS, name); 3009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30123ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadElement( 30133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> receiver_map) { 3014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------- S t a t e ------------- 3015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- lr : return address 3016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- r0 : key 3017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- r1 : receiver 3018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------------------------------- 3019589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind = receiver_map->elements_kind(); 30203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode(); 30213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DispatchMap(r1, r2, receiver_map, stub, DO_SMI_CHECK); 3023257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3024257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); 3025257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(ic, RelocInfo::CODE_TARGET); 3026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3027257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 30283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string()); 3029257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 30323ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( 30333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MapHandleList* receiver_maps, 30343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CodeHandleList* handler_ics) { 3035257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3036257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- lr : return address 3037257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r0 : key 3038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r1 : receiver 3039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3040257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 3041257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(r1, &miss); 3042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3043257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int receiver_count = receiver_maps->length(); 3044257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); 3045257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int current = 0; current < receiver_count; ++current) { 30463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ip, Operand(receiver_maps->at(current))); 3047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(r2, ip); 30483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(handler_ics->at(current), RelocInfo::CODE_TARGET, eq); 3049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&miss); 3052257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> miss_ic = isolate()->builtins()->KeyedLoadIC_Miss(); 3053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(miss_ic, RelocInfo::CODE_TARGET, al); 3054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Return the generated code. 30563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); 3057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 30603ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object, 30615913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index, 30623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> transition, 30633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 3064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 3065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : value 3066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- r1 : name 3067f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -- r2 : receiver 3068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 3069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 3070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 3071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 307244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = masm()->isolate()->counters(); 307344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_store_field(), 1, r3, r4); 3074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 30763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r1, Operand(name)); 3077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &miss); 3078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // r3 is used as scratch register. r1 and r2 keep their values if a jump to 3080f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // the miss label is generated. 30813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateStoreField(masm(), object, index, transition, r2, r1, r3, &miss); 3082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 3083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 308444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_store_field(), 1, r3, r4); 308544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss(); 3086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 3087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 30893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); 3090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30933ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreElement( 30943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> receiver_map) { 3095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------- S t a t e ------------- 3096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- r0 : value 3097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- r1 : key 3098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- r2 : receiver 3099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- lr : return address 3100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- r3 : scratch 3101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------------------------------- 3102589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind = receiver_map->elements_kind(); 3103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; 31043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> stub = 31053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch KeyedStoreElementStub(is_js_array, elements_kind, grow_mode_).GetCode(); 31063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 31073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DispatchMap(r2, r3, receiver_map, stub, DO_SMI_CHECK); 3108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 3110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(ic, RelocInfo::CODE_TARGET); 3111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 31133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string()); 3114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 31173ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( 31183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MapHandleList* receiver_maps, 31193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CodeHandleList* handler_stubs, 31203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MapHandleList* transitioned_maps) { 3121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r0 : value 3123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r1 : key 3124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r2 : receiver 3125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- lr : return address 3126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r3 : scratch 3127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 3129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(r2, &miss); 3130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int receiver_count = receiver_maps->length(); 3132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldr(r3, FieldMemOperand(r2, HeapObject::kMapOffset)); 31333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < receiver_count; ++i) { 31343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ip, Operand(receiver_maps->at(i))); 3135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(r3, ip); 31363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (transitioned_maps->at(i).is_null()) { 31373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, eq); 31383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 31393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label next_map; 31403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &next_map); 31413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r3, Operand(transitioned_maps->at(i))); 31423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, al); 31433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&next_map); 31443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&miss); 3148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss(); 3149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(miss_ic, RelocInfo::CODE_TARGET, al); 3150e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3151e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Return the generated code. 31523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); 3153e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 3154e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3155e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 31563ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> ConstructStubCompiler::CompileConstructStub( 31573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function) { 3158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 3159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : argc 3160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r1 : constructor 3161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 3162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- [sp] : last argument 3163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 3164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label generic_stub_call; 3165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use r7 for holding undefined which is used in several places below. 3167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(r7, Heap::kUndefinedValueRootIndex); 3168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 3170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check to see whether there are any break points in the function code. If 3171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // there are jump to the generic constructor stub which calls the actual 3172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // code for the function thereby hitting the break points. 3173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 3174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kDebugInfoOffset)); 3175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, r7); 3176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &generic_stub_call); 3177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 3178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the initial map and verify that it is in fact a map. 3180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 3181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 3182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 31833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(r2, &generic_stub_call); 3184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(r2, r3, r4, MAP_TYPE); 3185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &generic_stub_call); 3186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 3188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cannot construct functions this way. 3189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 3190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 3191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: initial map 3192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 3193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE); 3194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Check(ne, "Function constructed by construct stub."); 3195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 3196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Now allocate the JSObject in new space. 3198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 3199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 3200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: initial map 3201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 3202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset)); 32033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(r3, r4, r5, r6, &generic_stub_call, SIZE_IN_WORDS); 3204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocated the JSObject, now initialize the fields. Map is set to initial 3206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // map and properties and elements are set to empty fixed array. 3207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 3208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 3209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: initial map 3210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: object size (in words) 3211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject (not tagged) 3212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 3213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex); 3214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r5, r4); 3215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); 3216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r2, MemOperand(r5, kPointerSize, PostIndex)); 3217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset); 3218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); 3219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset); 3220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); 3221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the location of the first argument. The stack contains only the 3223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // argc arguments. 3224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r1, sp, Operand(r0, LSL, kPointerSizeLog2)); 3225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill all the in-object properties with undefined. 3227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 3228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: first argument 3229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: object size (in words) 3230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject (not tagged) 3231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r5: First in-object property of JSObject (not tagged) 3232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 3233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the initialized properties with a constant value or a passed argument 3234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // depending on the this.x = ...; assignment in the function. 32353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<SharedFunctionInfo> shared(function->shared()); 3236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < shared->this_property_assignments_count(); i++) { 3237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (shared->IsThisPropertyAssignmentArgument(i)) { 3238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label not_passed, next; 3239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the argument assigned to the property is actually passed. 3240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int arg_number = shared->GetThisPropertyAssignmentArgument(i); 3241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, Operand(arg_number)); 3242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(le, ¬_passed); 3243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Argument passed - find it on the stack. 3244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, MemOperand(r1, (arg_number + 1) * -kPointerSize)); 3245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r2, MemOperand(r5, kPointerSize, PostIndex)); 3246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(&next); 3247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(¬_passed); 3248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the property to undefined. 3249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r7, MemOperand(r5, kPointerSize, PostIndex)); 3250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&next); 3251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 3252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the property to the constant value. 3253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i)); 3254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, Operand(constant)); 3255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r2, MemOperand(r5, kPointerSize, PostIndex)); 3256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the unused in-object property fields with undefined. 32608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ASSERT(function->has_initial_map()); 3261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = shared->this_property_assignments_count(); 32628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang i < function->initial_map()->inobject_properties(); 3263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i++) { 3264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r7, MemOperand(r5, kPointerSize, PostIndex)); 3265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 3268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject (not tagged) 3269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move argc to r1 and the JSObject to return to r0 and tag it. 3270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r1, r0); 3271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, r4); 3272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ orr(r0, r0, Operand(kHeapObjectTag)); 3273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: JSObject 3275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: argc 3276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Remove caller arguments and receiver from the stack and return. 3277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2)); 3278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(kPointerSize)); 327944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = masm()->isolate()->counters(); 328044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->constructed_objects(), 1, r1, r2); 328144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->constructed_objects_stub(), 1, r1, r2); 3282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 3283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the generic stub in case the specialized code cannot handle the 3285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // construction. 3286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&generic_stub_call); 328744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> code = masm()->isolate()->builtins()->JSConstructStubGeneric(); 328844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Jump(code, RelocInfo::CODE_TARGET); 3289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 3291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(); 3292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 32953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#undef __ 32963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#define __ ACCESS_MASM(masm) 32973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 32983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 32993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadDictionaryElement( 33003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MacroAssembler* masm) { 33013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ---------- S t a t e -------------- 33023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- lr : return address 33033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r0 : key 33043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r1 : receiver 3305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 33063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label slow, miss_force_generic; 3307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 33083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register key = r0; 33093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register receiver = r1; 3310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 33113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(key, &miss_force_generic); 33123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(r2, Operand(key, ASR, kSmiTagSize)); 33133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset)); 33143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ LoadFromNumberDictionary(&slow, r4, key, r0, r2, r3, r5); 33153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Ret(); 3316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 33173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&slow); 33183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ IncrementCounter( 33193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->counters()->keyed_load_external_array_slow(), 33203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1, r2, r3); 3321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 33223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ---------- S t a t e -------------- 33233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- lr : return address 33243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r0 : key 33253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r1 : receiver 3326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 33273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> slow_ic = 33283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_Slow(); 33293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Jump(slow_ic, RelocInfo::CODE_TARGET); 3330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 33313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Miss case, call the runtime. 33323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&miss_force_generic); 3333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 33343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ---------- S t a t e -------------- 33353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- lr : return address 33363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r0 : key 33373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r1 : receiver 33383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------------------------------- 3339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 33403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> miss_ic = 33413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 33423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Jump(miss_ic, RelocInfo::CODE_TARGET); 33433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 3344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3345257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3346589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochstatic bool IsElementTypeSigned(ElementsKind elements_kind) { 33473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3348589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 3349589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 3350589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 33511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return true; 33521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3353589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 3354589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 3355589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 3356589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 33571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return false; 33581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3359589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 3360589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 3361589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_ELEMENTS: 33623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_SMI_ONLY_ELEMENTS: 3363589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_DOUBLE_ELEMENTS: 3364589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case DICTIONARY_ELEMENTS: 3365589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case NON_STRICT_ARGUMENTS_ELEMENTS: 33661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 33671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return false; 33681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 33693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return false; 33701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 33711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadExternalArray( 3374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MacroAssembler* masm, 3375589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind) { 33761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ---------- S t a t e -------------- 33771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- lr : return address 33781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- r0 : key 33791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- r1 : receiver 33801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 3381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss_force_generic, slow, failed_allocation; 33821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register key = r0; 33841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register receiver = r1; 33851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 3387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 33881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the key is a smi. 3390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(key, &miss_force_generic); 33911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset)); 339344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // r3: elements array 33941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the index is in range. 33961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset)); 339769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmp(key, ip); 33981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Unsigned comparison catches both negative and too-large values. 339969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ b(hs, &miss_force_generic); 34001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); 34021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // r3: base pointer of external storage 34031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // We are not untagging smi key and instead work with it 34051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // as if it was premultiplied by 2. 340669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT((kSmiTag == 0) && (kSmiTagSize == 1)); 34071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register value = r2; 34093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3410589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 34111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldrsb(value, MemOperand(r3, key, LSR, 1)); 34121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3413589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 3414589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 34151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldrb(value, MemOperand(r3, key, LSR, 1)); 34161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3417589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 34181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldrsh(value, MemOperand(r3, key, LSL, 0)); 34191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3420589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 34211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldrh(value, MemOperand(r3, key, LSL, 0)); 34221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3423589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 3424589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 34251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldr(value, MemOperand(r3, key, LSL, 1)); 34261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3427589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 34288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CpuFeatures::IsSupported(VFP3)) { 34291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CpuFeatures::Scope scope(VFP3); 34301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ add(r2, r3, Operand(key, LSL, 1)); 34311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ vldr(s0, r2, 0); 34321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 34331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldr(value, MemOperand(r3, key, LSL, 1)); 34341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 34351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3436589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 3437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(VFP3)) { 3438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(VFP3); 3439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ add(r2, r3, Operand(key, LSL, 2)); 3440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ vldr(d0, r2, 0); 3441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ add(r4, r3, Operand(key, LSL, 2)); 3443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // r4: pointer to the beginning of the double we want to load. 3444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldr(r2, MemOperand(r4, 0)); 3445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldr(r3, MemOperand(r4, Register::kSizeInBytes)); 3446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3448589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_ELEMENTS: 34493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_SMI_ONLY_ELEMENTS: 3450589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_DOUBLE_ELEMENTS: 3451589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case DICTIONARY_ELEMENTS: 3452589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case NON_STRICT_ARGUMENTS_ELEMENTS: 34531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 34541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 34551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 34561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For integer array types: 34581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // r2: value 3459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // For float array type: 34601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // s0: value (if VFP3 is supported) 34611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // r2: value (if VFP3 is not supported) 3462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // For double array type: 3463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // d0: value (if VFP3 is supported) 3464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // r2/r3: value (if VFP3 is not supported) 34651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3466589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_INT_ELEMENTS) { 34671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For the Int and UnsignedInt array types, we need to see whether 34681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the value can be represented in a Smi. If not, we need to convert 34691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // it to a HeapNumber. 34701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label box_int; 34711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmp(value, Operand(0xC0000000)); 34721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(mi, &box_int); 34731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Tag integer as smi and return it. 34741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(r0, Operand(value, LSL, kSmiTagSize)); 34751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(); 34761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&box_int); 34781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Allocate a HeapNumber for the result and perform int-to-double 34791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // conversion. Don't touch r0 or r1 as they are needed if allocation 34801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // fails. 34811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); 34821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ AllocateHeapNumber(r5, r3, r4, r6, &slow); 34831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Now we can use r0 for the result as key is not needed any more. 34841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(r0, r5); 34851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CpuFeatures::IsSupported(VFP3)) { 34871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CpuFeatures::Scope scope(VFP3); 34881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ vmov(s0, value); 34891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ vcvt_f64_s32(d0, s0); 34901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ sub(r3, r0, Operand(kHeapObjectTag)); 34911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ vstr(d0, r3, HeapNumber::kValueOffset); 34921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(); 34931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 3494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register dst1 = r1; 3495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register dst2 = r3; 3496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FloatingPointHelper::Destination dest = 3497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FloatingPointHelper::kCoreRegisters; 3498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FloatingPointHelper::ConvertIntToDouble(masm, 3499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch value, 3500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch dest, 3501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch d0, 3502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch dst1, 3503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch dst2, 3504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch r9, 3505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch s0); 3506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ str(dst1, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); 3507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ str(dst2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); 3508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 35091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 3510589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { 35111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // The test is different for unsigned int values. Since we need 35121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the value to be in the range of a positive smi, we can't 35131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // handle either of the top two bits being set in the value. 35148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CpuFeatures::IsSupported(VFP3)) { 35151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CpuFeatures::Scope scope(VFP3); 35161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label box_int, done; 35171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ tst(value, Operand(0xC0000000)); 35181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(ne, &box_int); 35191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Tag integer as smi and return it. 35201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(r0, Operand(value, LSL, kSmiTagSize)); 35211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(); 35221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&box_int); 35241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ vmov(s0, value); 35251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Allocate a HeapNumber for the result and perform int-to-double 35261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // conversion. Don't use r0 and r1 as AllocateHeapNumber clobbers all 35271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // registers - also when jumping due to exhausted young space. 35281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); 35291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ AllocateHeapNumber(r2, r3, r4, r6, &slow); 35301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ vcvt_f64_u32(d0, s0); 35321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ sub(r1, r2, Operand(kHeapObjectTag)); 35331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ vstr(d0, r1, HeapNumber::kValueOffset); 35341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(r0, r2); 35361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(); 35371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 35381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check whether unsigned integer fits into smi. 35391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label box_int_0, box_int_1, done; 35401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ tst(value, Operand(0x80000000)); 35411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(ne, &box_int_0); 35421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ tst(value, Operand(0x40000000)); 35431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(ne, &box_int_1); 35441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Tag integer as smi and return it. 35451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(r0, Operand(value, LSL, kSmiTagSize)); 35461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(); 35471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register hiword = value; // r2. 35491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register loword = r3; 35501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&box_int_0); 35521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Integer does not have leading zeros. 3553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateUInt2Double(masm, hiword, loword, r4, 0); 35541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(&done); 35551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&box_int_1); 35571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Integer has one leading zero. 3558257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateUInt2Double(masm, hiword, loword, r4, 1); 35591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&done); 35621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Integer was converted to double in registers hiword:loword. 35631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Wrap it into a HeapNumber. Don't use r0 and r1 as AllocateHeapNumber 35641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // clobbers all registers - also when jumping due to exhausted young 35651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // space. 35661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); 35671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ AllocateHeapNumber(r4, r5, r7, r6, &slow); 35681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ str(hiword, FieldMemOperand(r4, HeapNumber::kExponentOffset)); 35701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ str(loword, FieldMemOperand(r4, HeapNumber::kMantissaOffset)); 35711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(r0, r4); 35731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(); 35741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 3575589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 35761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For the floating-point array type, we need to always allocate a 35771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // HeapNumber. 35788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CpuFeatures::IsSupported(VFP3)) { 35791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CpuFeatures::Scope scope(VFP3); 35801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Allocate a HeapNumber for the result. Don't use r0 and r1 as 35811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // AllocateHeapNumber clobbers all registers - also when jumping due to 35821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // exhausted young space. 35831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); 35841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ AllocateHeapNumber(r2, r3, r4, r6, &slow); 35851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ vcvt_f64_f32(d0, s0); 35861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ sub(r1, r2, Operand(kHeapObjectTag)); 35871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ vstr(d0, r1, HeapNumber::kValueOffset); 35881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(r0, r2); 35901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(); 35911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 35921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Allocate a HeapNumber for the result. Don't use r0 and r1 as 35931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // AllocateHeapNumber clobbers all registers - also when jumping due to 35941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // exhausted young space. 35951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); 35961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ AllocateHeapNumber(r3, r4, r5, r6, &slow); 35971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // VFP is not available, do manual single to double conversion. 35981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // r2: floating point value (binary32) 36001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // r3: heap number for result 36011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Extract mantissa to r0. OK to clobber r0 now as there are no jumps to 36031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the slow case from here. 36041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ and_(r0, value, Operand(kBinary32MantissaMask)); 36051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Extract exponent to r1. OK to clobber r1 now as there are no jumps to 36071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the slow case from here. 36081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(r1, Operand(value, LSR, kBinary32MantissaBits)); 36091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ and_(r1, r1, Operand(kBinary32ExponentMask >> kBinary32MantissaBits)); 36101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label exponent_rebiased; 36121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ teq(r1, Operand(0x00)); 36131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(eq, &exponent_rebiased); 36141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ teq(r1, Operand(0xff)); 36161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(r1, Operand(0x7ff), LeaveCC, eq); 36171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(eq, &exponent_rebiased); 36181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Rebias exponent. 36201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ add(r1, 36211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block r1, 36221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Operand(-kBinary32ExponentBias + HeapNumber::kExponentBias)); 36231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&exponent_rebiased); 36251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ and_(r2, value, Operand(kBinary32SignMask)); 36261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block value = no_reg; 36271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ orr(r2, r2, Operand(r1, LSL, HeapNumber::kMantissaBitsInTopWord)); 36281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Shift mantissa. 36301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block static const int kMantissaShiftForHiWord = 36311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord; 36321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block static const int kMantissaShiftForLoWord = 36341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block kBitsPerInt - kMantissaShiftForHiWord; 36351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ orr(r2, r2, Operand(r0, LSR, kMantissaShiftForHiWord)); 36371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(r0, Operand(r0, LSL, kMantissaShiftForLoWord)); 36381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ str(r2, FieldMemOperand(r3, HeapNumber::kExponentOffset)); 36401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ str(r0, FieldMemOperand(r3, HeapNumber::kMantissaOffset)); 36411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(r0, r3); 36431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(); 36441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 3645589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 3646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(VFP3)) { 3647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(VFP3); 3648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Allocate a HeapNumber for the result. Don't use r0 and r1 as 3649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // AllocateHeapNumber clobbers all registers - also when jumping due to 3650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // exhausted young space. 3651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); 3652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AllocateHeapNumber(r2, r3, r4, r6, &slow); 3653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sub(r1, r2, Operand(kHeapObjectTag)); 3654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ vstr(d0, r1, HeapNumber::kValueOffset); 3655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(r0, r2); 3657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 3658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Allocate a HeapNumber for the result. Don't use r0 and r1 as 3660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // AllocateHeapNumber clobbers all registers - also when jumping due to 3661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // exhausted young space. 3662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(r7, Heap::kHeapNumberMapRootIndex); 3663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AllocateHeapNumber(r4, r5, r6, r7, &slow); 3664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ str(r2, FieldMemOperand(r4, HeapNumber::kMantissaOffset)); 3666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ str(r3, FieldMemOperand(r4, HeapNumber::kExponentOffset)); 3667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(r0, r4); 3668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 3669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 36701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 36721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Tag integer as smi and return it. 36731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(r0, Operand(value, LSL, kSmiTagSize)); 36741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(); 36751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 36761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Slow case, key and receiver still in r0 and r1. 36781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&slow); 367944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter( 3680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->counters()->keyed_load_external_array_slow(), 368144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1, r2, r3); 36821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ---------- S t a t e -------------- 36841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- lr : return address 36851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- r0 : key 36861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- r1 : receiver 36871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 36881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Push(r1, r0); 36901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 36921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 36943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> stub = 36953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 36963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(stub, RelocInfo::CODE_TARGET); 36971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 36981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreExternalArray( 3701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MacroAssembler* masm, 3702589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind) { 37031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ---------- S t a t e -------------- 37041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- r0 : value 37051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- r1 : key 37061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- r2 : receiver 37071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- lr : return address 37081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 3709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label slow, check_heap_number, miss_force_generic; 37101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Register usage. 37121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register value = r0; 37131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register key = r1; 37141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register receiver = r2; 37151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // r3 mostly holds the elements array or the destination external array. 37161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 3718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 37191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the key is a smi. 3721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(key, &miss_force_generic); 37221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 372369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset)); 372469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 372544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the index is in range 37261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset)); 372769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmp(key, ip); 37281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Unsigned comparison catches both negative and too-large values. 3729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ b(hs, &miss_force_generic); 37301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Handle both smis and HeapNumbers in the fast path. Go to the 37321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // runtime for all other kinds of values. 37331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // r3: external array. 3734589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) { 373544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Double to pixel conversion is only implemented in the runtime for now. 373644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ JumpIfNotSmi(value, &slow); 373744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 373844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ JumpIfNotSmi(value, &check_heap_number); 373944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 374044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ SmiUntag(r5, value); 37411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); 37421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // r3: base pointer of external storage. 37441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // r5: value (integer). 37453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3746589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 374744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Clamp the value to [0..255]. 374844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Usat(r5, 8, Operand(r5)); 374969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ strb(r5, MemOperand(r3, key, LSR, 1)); 375044f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3751589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 3752589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 375369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ strb(r5, MemOperand(r3, key, LSR, 1)); 37541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3755589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 3756589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 375769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ strh(r5, MemOperand(r3, key, LSL, 0)); 37581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3759589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 3760589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 376169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ str(r5, MemOperand(r3, key, LSL, 1)); 37621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3763589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 37641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Perform int-to-float conversion and store to memory. 376569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ SmiUntag(r4, key); 3766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StoreIntAsFloat(masm, r3, r4, r5, r6, r7, r9); 3767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3768589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 376969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ add(r3, r3, Operand(key, LSL, 2)); 3770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // r3: effective address of the double element 3771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FloatingPointHelper::Destination destination; 3772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(VFP3)) { 3773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch destination = FloatingPointHelper::kVFPRegisters; 3774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch destination = FloatingPointHelper::kCoreRegisters; 3776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FloatingPointHelper::ConvertIntToDouble( 3778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm, r5, destination, 3779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch d0, r6, r7, // These are: double_dst, dst1, dst2. 3780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch r4, s2); // These are: scratch2, single_scratch. 3781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (destination == FloatingPointHelper::kVFPRegisters) { 3782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(VFP3); 3783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ vstr(d0, r3, 0); 3784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ str(r6, MemOperand(r3, 0)); 3786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ str(r7, MemOperand(r3, Register::kSizeInBytes)); 3787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 37881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3789589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_ELEMENTS: 37903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_SMI_ONLY_ELEMENTS: 3791589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_DOUBLE_ELEMENTS: 3792589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case DICTIONARY_ELEMENTS: 3793589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case NON_STRICT_ARGUMENTS_ELEMENTS: 37941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 37951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 37961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 37971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Entry registers are intact, r0 holds the value which is the return value. 37991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(); 38001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3801589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) { 380244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // r3: external array. 380344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&check_heap_number); 380444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CompareObjectType(value, r5, r6, HEAP_NUMBER_TYPE); 380544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ b(ne, &slow); 38061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 380744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); 38081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 380944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // r3: base pointer of external storage. 38101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 381144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // The WebGL specification leaves the behavior of storing NaN and 381244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // +/-Infinity into integer arrays basically undefined. For more 381344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // reproducible behavior, convert these to zero. 38148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CpuFeatures::IsSupported(VFP3)) { 381544f0eee88ff00398ff7f715fab053374d808c90dSteve Block CpuFeatures::Scope scope(VFP3); 38161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3817589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 381844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // vldr requires offset to be a multiple of 4 so we can not 381944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // include -kHeapObjectTag into it. 382044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ sub(r5, r0, Operand(kHeapObjectTag)); 382144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ vldr(d0, r5, HeapNumber::kValueOffset); 382269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ add(r5, r3, Operand(key, LSL, 1)); 382344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ vcvt_f32_f64(s0, d0); 382444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ vstr(s0, r5, 0); 3825589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 3826257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sub(r5, r0, Operand(kHeapObjectTag)); 3827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ vldr(d0, r5, HeapNumber::kValueOffset); 382869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ add(r5, r3, Operand(key, LSL, 2)); 3829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ vstr(d0, r5, 0); 38301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 383144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Hoisted load. vldr requires offset to be a multiple of 4 so we can 383244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // not include -kHeapObjectTag into it. 383344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ sub(r5, value, Operand(kHeapObjectTag)); 383444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ vldr(d0, r5, HeapNumber::kValueOffset); 38353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ EmitECMATruncate(r5, d0, s2, r6, r7, r9); 383644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 38373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3838589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 3839589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 384069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ strb(r5, MemOperand(r3, key, LSR, 1)); 384144f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3842589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 3843589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 384469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ strh(r5, MemOperand(r3, key, LSL, 0)); 384544f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3846589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 3847589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 384869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ str(r5, MemOperand(r3, key, LSL, 1)); 384944f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3850589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 3851589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 3852589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 3853589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_ELEMENTS: 38543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_SMI_ONLY_ELEMENTS: 3855589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_DOUBLE_ELEMENTS: 3856589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case DICTIONARY_ELEMENTS: 3857589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case NON_STRICT_ARGUMENTS_ELEMENTS: 385844f0eee88ff00398ff7f715fab053374d808c90dSteve Block UNREACHABLE(); 385944f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 386044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 38611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 38621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 38631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Entry registers are intact, r0 holds the value which is the return 38641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // value. 38651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(); 38661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 386744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // VFP3 is not available do manual conversions. 386844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ ldr(r5, FieldMemOperand(value, HeapNumber::kExponentOffset)); 386944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ ldr(r6, FieldMemOperand(value, HeapNumber::kMantissaOffset)); 387044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3871589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 387244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label done, nan_or_infinity_or_zero; 387344f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const int kMantissaInHiWordShift = 387444f0eee88ff00398ff7f715fab053374d808c90dSteve Block kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord; 387544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 387644f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const int kMantissaInLoWordShift = 387744f0eee88ff00398ff7f715fab053374d808c90dSteve Block kBitsPerInt - kMantissaInHiWordShift; 387844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 387944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Test for all special exponent values: zeros, subnormal numbers, NaNs 388044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // and infinities. All these should be converted to 0. 388144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(r7, Operand(HeapNumber::kExponentMask)); 388244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ and_(r9, r5, Operand(r7), SetCC); 388344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ b(eq, &nan_or_infinity_or_zero); 388444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 388544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ teq(r9, Operand(r7)); 388644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(r9, Operand(kBinary32ExponentMask), LeaveCC, eq); 388744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ b(eq, &nan_or_infinity_or_zero); 388844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 388944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Rebias exponent. 389044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(r9, Operand(r9, LSR, HeapNumber::kExponentShift)); 389144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ add(r9, 389244f0eee88ff00398ff7f715fab053374d808c90dSteve Block r9, 389344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Operand(kBinary32ExponentBias - HeapNumber::kExponentBias)); 389444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 389544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(r9, Operand(kBinary32MaxExponent)); 389644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ and_(r5, r5, Operand(HeapNumber::kSignMask), LeaveCC, gt); 389744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ orr(r5, r5, Operand(kBinary32ExponentMask), LeaveCC, gt); 389844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ b(gt, &done); 389944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 390044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(r9, Operand(kBinary32MinExponent)); 390144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ and_(r5, r5, Operand(HeapNumber::kSignMask), LeaveCC, lt); 390244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ b(lt, &done); 390344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 390444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ and_(r7, r5, Operand(HeapNumber::kSignMask)); 390544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ and_(r5, r5, Operand(HeapNumber::kMantissaMask)); 390644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ orr(r7, r7, Operand(r5, LSL, kMantissaInHiWordShift)); 390744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ orr(r7, r7, Operand(r6, LSR, kMantissaInLoWordShift)); 390844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ orr(r5, r7, Operand(r9, LSL, kBinary32ExponentShift)); 390944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 391044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&done); 391169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ str(r5, MemOperand(r3, key, LSL, 1)); 391244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Entry registers are intact, r0 holds the value which is the return 391344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // value. 391444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Ret(); 391544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 391644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&nan_or_infinity_or_zero); 391744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ and_(r7, r5, Operand(HeapNumber::kSignMask)); 391844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ and_(r5, r5, Operand(HeapNumber::kMantissaMask)); 391944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ orr(r9, r9, r7); 392044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ orr(r9, r9, Operand(r5, LSL, kMantissaInHiWordShift)); 392144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ orr(r5, r9, Operand(r6, LSR, kMantissaInLoWordShift)); 392244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ b(&done); 3923589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 392469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ add(r7, r3, Operand(key, LSL, 2)); 3925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // r7: effective address of destination element. 3926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ str(r6, MemOperand(r7, 0)); 3927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ str(r5, MemOperand(r7, Register::kSizeInBytes)); 3928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 392944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 39303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool is_signed_type = IsElementTypeSigned(elements_kind); 393144f0eee88ff00398ff7f715fab053374d808c90dSteve Block int meaningfull_bits = is_signed_type ? (kBitsPerInt - 1) : kBitsPerInt; 393244f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t min_value = is_signed_type ? 0x80000000 : 0x00000000; 393344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 393444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label done, sign; 393544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 393644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Test for all special exponent values: zeros, subnormal numbers, NaNs 393744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // and infinities. All these should be converted to 0. 393844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(r7, Operand(HeapNumber::kExponentMask)); 393944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ and_(r9, r5, Operand(r7), SetCC); 394044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq); 394144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ b(eq, &done); 394244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 394344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ teq(r9, Operand(r7)); 394444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq); 394544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ b(eq, &done); 394644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 394744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Unbias exponent. 394844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(r9, Operand(r9, LSR, HeapNumber::kExponentShift)); 394944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ sub(r9, r9, Operand(HeapNumber::kExponentBias), SetCC); 395044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // If exponent is negative then result is 0. 395144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, mi); 395244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ b(mi, &done); 395344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 395444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // If exponent is too big then result is minimal value. 395544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(r9, Operand(meaningfull_bits - 1)); 395644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(r5, Operand(min_value), LeaveCC, ge); 395744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ b(ge, &done); 395844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 395944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ and_(r7, r5, Operand(HeapNumber::kSignMask), SetCC); 396044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ and_(r5, r5, Operand(HeapNumber::kMantissaMask)); 396144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ orr(r5, r5, Operand(1u << HeapNumber::kMantissaBitsInTopWord)); 396244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 396344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ rsb(r9, r9, Operand(HeapNumber::kMantissaBitsInTopWord), SetCC); 396444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(r5, Operand(r5, LSR, r9), LeaveCC, pl); 396544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ b(pl, &sign); 396644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 396744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ rsb(r9, r9, Operand(0, RelocInfo::NONE)); 396844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(r5, Operand(r5, LSL, r9)); 396944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ rsb(r9, r9, Operand(meaningfull_bits)); 397044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ orr(r5, r5, Operand(r6, LSR, r9)); 397144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 397244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&sign); 397344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ teq(r7, Operand(0, RelocInfo::NONE)); 397444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ rsb(r5, r5, Operand(0, RelocInfo::NONE), LeaveCC, ne); 397544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 397644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&done); 39773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3978589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 3979589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 398069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ strb(r5, MemOperand(r3, key, LSR, 1)); 398144f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3982589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 3983589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 398469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ strh(r5, MemOperand(r3, key, LSL, 0)); 398544f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3986589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 3987589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 398869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ str(r5, MemOperand(r3, key, LSL, 1)); 398944f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3990589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 3991589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 3992589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 3993589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_ELEMENTS: 39943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_SMI_ONLY_ELEMENTS: 3995589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_DOUBLE_ELEMENTS: 3996589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case DICTIONARY_ELEMENTS: 3997589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case NON_STRICT_ARGUMENTS_ELEMENTS: 399844f0eee88ff00398ff7f715fab053374d808c90dSteve Block UNREACHABLE(); 399944f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 400044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 40011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 40021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 40031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 40041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 4005257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Slow case, key and receiver still in r0 and r1. 40061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&slow); 4007257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter( 4008257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->counters()->keyed_load_external_array_slow(), 4009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1, r2, r3); 40101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 40111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ---------- S t a t e -------------- 40121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- lr : return address 4013257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r0 : key 4014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r1 : receiver 40151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 4016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> slow_ic = 4017257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->builtins()->KeyedStoreIC_Slow(); 4018257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(slow_ic, RelocInfo::CODE_TARGET); 40191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 4020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Miss case, call the runtime. 4021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 40221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 4023257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ---------- S t a t e -------------- 4024257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- lr : return address 4025257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r0 : key 4026257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r1 : receiver 4027257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 4028257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4029257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> miss_ic = 4030257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 4031257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(miss_ic, RelocInfo::CODE_TARGET); 4032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 4033257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4035257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) { 4036257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 4037257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- lr : return address 4038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r0 : key 4039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r1 : receiver 4040257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 4041257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss_force_generic; 4042e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4043257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 4044257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 40451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 4046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is a smi. 4047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(r0, &miss_force_generic); 4048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the elements array. 4050257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldr(r2, FieldMemOperand(r1, JSObject::kElementsOffset)); 4051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AssertFastElements(r2); 4052257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is within bounds. 4054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldr(r3, FieldMemOperand(r2, FixedArray::kLengthOffset)); 4055257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(r0, Operand(r3)); 4056257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ b(hs, &miss_force_generic); 4057257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4058257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the result and make sure it's not the hole. 4059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ add(r3, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 406069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); 4061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldr(r4, 4062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MemOperand(r3, r0, LSL, kPointerSizeLog2 - kSmiTagSize)); 4063257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 4064257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(r4, ip); 4065257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ b(eq, &miss_force_generic); 4066257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(r0, r4); 4067257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 4068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 40703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> stub = 40713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 40723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(stub, RelocInfo::CODE_TARGET); 4073257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 4074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 40763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastDoubleElement( 40773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MacroAssembler* masm) { 40783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------- S t a t e ------------- 40793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- lr : return address 40803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r0 : key 40813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r1 : receiver 40823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------------------------------- 40833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label miss_force_generic, slow_allocate_heapnumber; 40843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 40853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register key_reg = r0; 40863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register receiver_reg = r1; 40873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register elements_reg = r2; 40883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register heap_number_reg = r2; 40893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register indexed_double_offset = r3; 40903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register scratch = r4; 40913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register scratch2 = r5; 40923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register scratch3 = r6; 40933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register heap_number_map = r7; 40943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 40953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 40963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // have been verified by the caller to not be a smi. 40973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 40983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is a smi. 40993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(key_reg, &miss_force_generic); 41003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Get the elements array. 41023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ldr(elements_reg, 41033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 41043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is within bounds. 41063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ldr(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); 41073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp(key_reg, Operand(scratch)); 41083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ b(hs, &miss_force_generic); 41093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Load the upper word of the double in the fixed array and test for NaN. 41113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ add(indexed_double_offset, elements_reg, 41123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Operand(key_reg, LSL, kDoubleSizeLog2 - kSmiTagSize)); 41133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t upper_32_offset = FixedArray::kHeaderSize + sizeof(kHoleNanLower32); 41143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ldr(scratch, FieldMemOperand(indexed_double_offset, upper_32_offset)); 41153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp(scratch, Operand(kHoleNanUpper32)); 41163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ b(&miss_force_generic, eq); 41173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Non-NaN. Allocate a new heap number and copy the double value into it. 41193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); 41203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ AllocateHeapNumber(heap_number_reg, scratch2, scratch3, 41213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch heap_number_map, &slow_allocate_heapnumber); 41223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Don't need to reload the upper 32 bits of the double, it's already in 41243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // scratch. 41253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ str(scratch, FieldMemOperand(heap_number_reg, 41263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HeapNumber::kExponentOffset)); 41273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ldr(scratch, FieldMemOperand(indexed_double_offset, 41283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FixedArray::kHeaderSize)); 41293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ str(scratch, FieldMemOperand(heap_number_reg, 41303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HeapNumber::kMantissaOffset)); 41313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(r0, heap_number_reg); 41333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Ret(); 41343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&slow_allocate_heapnumber); 41363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> slow_ic = 41373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_Slow(); 41383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Jump(slow_ic, RelocInfo::CODE_TARGET); 41393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&miss_force_generic); 41413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> miss_ic = 41423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 41433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Jump(miss_ic, RelocInfo::CODE_TARGET); 41443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 41453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastElement( 41483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler* masm, 41493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_js_array, 41503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind elements_kind, 41513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch KeyedAccessGrowMode grow_mode) { 4152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 4153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r0 : value 4154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r1 : key 4155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r2 : receiver 4156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- lr : return address 4157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r3 : scratch 4158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r4 : scratch (elements) 4159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 41603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label miss_force_generic, transition_elements_kind, grow, slow; 41613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label finish_store, check_capacity; 4162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register value_reg = r0; 4164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register key_reg = r1; 4165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register receiver_reg = r2; 41663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch = r4; 41673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register elements_reg = r3; 41683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register length_reg = r5; 41693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch2 = r6; 4170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 4172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 4173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is a smi. 41753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(key_reg, &miss_force_generic); 4176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 41773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { 41783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfNotSmi(value_reg, &transition_elements_kind); 41793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 418085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 418185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // Check that the key is within bounds. 41823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(elements_reg, 41833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 4184257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (is_js_array) { 4185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldr(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); 4186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 4187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldr(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); 4188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 4189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compare smis. 4190257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(key_reg, scratch); 41913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) { 41923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(hs, &grow); 41933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 41943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(hs, &miss_force_generic); 41953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 41973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure elements is a fast element array, not 'cow'. 41983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(elements_reg, 41993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 42003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kFixedArrayMapRootIndex, 42013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss_force_generic, 42023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DONT_DO_SMI_CHECK); 42035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 42043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&finish_store); 42053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { 42063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(scratch, 42073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch elements_reg, 42083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 42093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); 42103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(scratch, 42113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 42123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand(key_reg, LSL, kPointerSizeLog2 - kSmiTagSize)); 42133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(value_reg, MemOperand(scratch)); 42143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 42153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(elements_kind == FAST_ELEMENTS); 42163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(scratch, 42173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch elements_reg, 42183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 42193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); 42203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(scratch, 42213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 42223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand(key_reg, LSL, kPointerSizeLog2 - kSmiTagSize)); 42233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(value_reg, MemOperand(scratch)); 42243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(receiver_reg, value_reg); 42253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWrite(elements_reg, // Object. 42263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, // Address. 42273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver_reg, // Value. 42283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kLRHasNotBeenSaved, 42293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs); 42303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // value_reg (r0) is preserved. 4232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Done. 4233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 4234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 4236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = 4237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 4238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(ic, RelocInfo::CODE_TARGET); 42393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&transition_elements_kind); 42413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); 42423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(ic_miss, RelocInfo::CODE_TARGET); 42433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) { 42453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Grow the array by a single element if possible. 42463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&grow); 42473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure the array is only growing by a single element, anything else 42493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // must be handled by the runtime. Flags already set by previous compare. 42503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &miss_force_generic); 42513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for the empty array, and preallocate a small backing store if 42533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // possible. 42543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(length_reg, 42553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); 42563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(elements_reg, 42573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 42583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(elements_reg, Heap::kEmptyFixedArrayRootIndex); 42593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &check_capacity); 42603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int size = FixedArray::SizeFor(JSArray::kPreallocatedArrayElements); 42623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(size, elements_reg, scratch, scratch2, &slow, 42633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TAG_OBJECT); 42643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(scratch, Heap::kFixedArrayMapRootIndex); 42663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(scratch, FieldMemOperand(elements_reg, JSObject::kMapOffset)); 42673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(scratch, Operand(Smi::FromInt(JSArray::kPreallocatedArrayElements))); 42683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); 42693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); 42703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 1; i < JSArray::kPreallocatedArrayElements; ++i) { 42713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(scratch, FieldMemOperand(elements_reg, FixedArray::SizeFor(i))); 42723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 42733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the element at index zero. 42753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(value_reg, FieldMemOperand(elements_reg, FixedArray::SizeFor(0))); 42763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Install the new backing store in the JSArray. 42783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(elements_reg, 42793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 42803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(receiver_reg, JSObject::kElementsOffset, elements_reg, 42813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, kLRHasNotBeenSaved, kDontSaveFPRegs, 42823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 42833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Increment the length of the array. 42853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(length_reg, Operand(Smi::FromInt(1))); 42863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); 42873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(); 42883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&check_capacity); 42903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for cow elements, in general they are not handled by this stub 42913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(elements_reg, 42923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 42933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kFixedCOWArrayMapRootIndex, 42943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss_force_generic, 42953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DONT_DO_SMI_CHECK); 42963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); 42983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(length_reg, scratch); 42993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(hs, &slow); 43003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Grow the array and finish the store. 43023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(length_reg, length_reg, Operand(Smi::FromInt(1))); 43033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); 43043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&finish_store); 43053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&slow); 43073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow(); 43083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(ic_slow, RelocInfo::CODE_TARGET); 43093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 43101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 43111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 43121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 43133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( 43143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MacroAssembler* masm, 43153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_js_array, 43163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch KeyedAccessGrowMode grow_mode) { 43173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------- S t a t e ------------- 43183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r0 : value 43193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r1 : key 43203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r2 : receiver 43213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- lr : return address 43223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r3 : scratch 43233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r4 : scratch 43243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- r5 : scratch 43253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------------------------------- 43263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label miss_force_generic, transition_elements_kind, grow, slow; 43273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label finish_store, check_capacity; 43283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 43293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register value_reg = r0; 43303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register key_reg = r1; 43313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register receiver_reg = r2; 43323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register elements_reg = r3; 43333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1 = r4; 43343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch2 = r5; 43353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch3 = r6; 43363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register scratch4 = r7; 43373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register length_reg = r7; 43383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 43393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 43403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // have been verified by the caller to not be a smi. 43413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(key_reg, &miss_force_generic); 43423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 43433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ldr(elements_reg, 43443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 43453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 43463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is within bounds. 43473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (is_js_array) { 43483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(scratch1, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); 43493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 43503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(scratch1, 43513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); 43523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 43533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Compare smis, unsigned compare catches both negative and out-of-bound 43543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // indexes. 43553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(key_reg, scratch1); 43563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (grow_mode == ALLOW_JSARRAY_GROWTH) { 43573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(hs, &grow); 43585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } else { 43593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(hs, &miss_force_generic); 43605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 43613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 43623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&finish_store); 43633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ StoreNumberToDoubleElements(value_reg, 43643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch key_reg, 43653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver_reg, 43663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch elements_reg, 43673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, 43683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch2, 43693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch3, 43703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch4, 43713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &transition_elements_kind); 43723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Ret(); 43733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 43743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Handle store cache miss, replacing the ic with the generic stub. 43753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&miss_force_generic); 43763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> ic = 43773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 43783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Jump(ic, RelocInfo::CODE_TARGET); 43793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&transition_elements_kind); 43813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); 43823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(ic_miss, RelocInfo::CODE_TARGET); 43833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) { 43853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Grow the array by a single element if possible. 43863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&grow); 43873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure the array is only growing by a single element, anything else 43893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // must be handled by the runtime. Flags already set by previous compare. 43903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &miss_force_generic); 43913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Transition on values that can't be stored in a FixedDoubleArray. 43933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label value_is_smi; 43943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(value_reg, &value_is_smi); 43953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset)); 43963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(scratch1, Heap::kHeapNumberMapRootIndex); 43973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &transition_elements_kind); 43983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&value_is_smi); 43993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for the empty array, and preallocate a small backing store if 44013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // possible. 44023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(length_reg, 44033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); 44043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(elements_reg, 44053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 44063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(elements_reg, Heap::kEmptyFixedArrayRootIndex); 44073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &check_capacity); 44083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int size = FixedDoubleArray::SizeFor(JSArray::kPreallocatedArrayElements); 44103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(size, elements_reg, scratch1, scratch2, &slow, 44113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TAG_OBJECT); 44123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Initialize the new FixedDoubleArray. Leave elements unitialized for 44143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // efficiency, they are guaranteed to be initialized before use. 44153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(scratch1, Heap::kFixedDoubleArrayMapRootIndex); 44163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(scratch1, FieldMemOperand(elements_reg, JSObject::kMapOffset)); 44173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(scratch1, 44183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand(Smi::FromInt(JSArray::kPreallocatedArrayElements))); 44193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(scratch1, 44203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(elements_reg, FixedDoubleArray::kLengthOffset)); 44213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Install the new backing store in the JSArray. 44233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(elements_reg, 44243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 44253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(receiver_reg, JSObject::kElementsOffset, elements_reg, 44263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, kLRHasNotBeenSaved, kDontSaveFPRegs, 44273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 44283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Increment the length of the array. 44303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(length_reg, Operand(Smi::FromInt(1))); 44313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); 44323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&finish_store); 44333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&check_capacity); 44353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure that the backing store can hold additional elements. 44363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(scratch1, 44373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(elements_reg, FixedDoubleArray::kLengthOffset)); 44383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(length_reg, scratch1); 44393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(hs, &slow); 44403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Grow the array and finish the store. 44423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(length_reg, length_reg, Operand(Smi::FromInt(1))); 44433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); 44443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&finish_store); 44453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&slow); 44473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow(); 44483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(ic_slow, RelocInfo::CODE_TARGET); 44493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 44503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 44513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 44523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 4454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 4456f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 4457f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_ARM 4458